如何在R中将DataFrame转换为基因型交叉计数汇总矩阵?
问题描述
现有如下R语言DataFrame:
df <- as.data.frame( FID = c("1234", "1234", "4567", "4567", "2345", "2345"), genotype_column = c("chr26_1234_A_G", "chr26_1234_A_G", "chr26_1234_A_G", "chr26_1234_A_G", "chr26_1234_A_G", "chr26_1234_A_G"), dataset = c("type1", "type2", "type1", "type2", "type1", "type2"), genotype_type = c("AA", "Aa", "AA", "aa", "AA", "AA") )
需要生成一个3×3的交叉统计矩阵:行对应type1的三种基因型(AA、Aa、aa),列对应type2的三种基因型;矩阵元素为同一FID个体在两个dataset下对应基因型组合的出现次数,对角线为同基因型共现数,非对角线为不同基因型共现数。目标矩阵结构如下:
matrix(0, nrow = 3, ncol = 3, dimnames = list(c("AA_type1", "Aa_type1", "aa_type1"), c("AA_type2", "Aa_type2", "aa_type2")))
实现方法
可以通过数据重塑+交叉制表完成,无需额外复杂函数,以下提供两种常用方案:
方案1:Base R 实现
- 先将长表转为每个FID对应type1和type2基因型的宽表:
# 按FID拆分,提取两个dataset的基因型 wide_df <- reshape(df, idvar = "FID", timevar = "dataset", direction = "wide") # 简化列名 colnames(wide_df) <- c("FID", "genotype_type1", "genotype_type2")
- 生成交叉统计表并调整格式:
# 统计基因型组合出现次数 cross_table <- table(wide_df$genotype_type1, wide_df$genotype_type2) # 匹配目标行列名称格式 rownames(cross_table) <- paste0(rownames(cross_table), "_type1") colnames(cross_table) <- paste0(colnames(cross_table), "_type2") # 确保所有基因型类别都存在(避免缺失导致矩阵维度错误) all_genotypes <- c("AA", "Aa", "aa") cross_table <- cross_table[paste0(all_genotypes, "_type1"), paste0(all_genotypes, "_type2")] # 缺失组合填充0 cross_table[is.na(cross_table)] <- 0
运行后针对示例数据的输出结果:
AA_type2 Aa_type2 aa_type2 AA_type1 1 0 1 Aa_type1 1 0 0 aa_type1 0 0 0
方案2:tidyverse 实现
若习惯使用tidyverse语法,步骤如下:
library(tidyverse) cross_table <- df %>% # 转宽表,每个FID对应两个dataset的基因型 pivot_wider(id_cols = FID, names_from = dataset, values_from = genotype_type) %>% # 统计每种基因型组合的数量 count(type1, type2) %>% # 转回宽表并填充缺失值为0 pivot_wider(names_from = type2, values_from = n, values_fill = 0) %>% # 补充所有可能的基因型类别,确保矩阵为3×3 rownames_to_column("type1") %>% complete(type1 = c("AA", "Aa", "aa"), type2 = c("AA", "Aa", "aa"), fill = list(n = 0)) %>% pivot_wider(names_from = type2, values_from = n) %>% column_to_rownames("type1") # 调整行列名称为目标格式 rownames(cross_table) <- paste0(rownames(cross_table), "_type1") colnames(cross_table) <- paste0(colnames(cross_table), "_type2")
核心逻辑说明
- 先将每个FID的两个dataset基因型配对,再统计每种配对的出现次数
- 补充缺失基因型类别是为了保证矩阵始终为3×3结构,避免因部分基因型未出现导致维度不足
内容的提问来源于stack exchange,提问作者Khaleesi95
相关产品推荐
相关产品推荐

