如何将0/1标记的基因型数据框按多条件折叠转换?
基因型0/1标记到位点等位基因格式的转换方案
原始数据集
df <- structure(list(Genotype = 1:5, Locus_1a = c(0L, 1L, 1L, 1L, 1L ), Locus_1b = c(1L, 1L, 0L, 1L, 0L), Locus_1c = c(1L, 0L, 1L, 1L, 0L), Locus_2a = c(0L, 1L, 1L, 0L, 0L), Locus_2b = c(1L, 1L, 0L, 1L, 1L), Locus_2c = c(1L, 0L, 1L, 1L, 0L)), class = "data.frame", row.names = c(NA, -5L))
转换需求
将上述0/1标记的基因型矩阵转换为按位点拆分的等位基因列,规则如下:
- 二倍体个体保留2个等位基因(纯合子需重复显示同一等位基因)
- 三倍体个体保留3个等位基因
- 等位基因由原始列名末尾的字母(a/b/c)表示
实现代码(R语言)
library(tidyverse) # 处理单个位点的函数 process_locus <- function(locus_data, locus_name) { # 筛选当前位点的所有等位基因列 allele_cols <- grep(paste0("^", locus_name), colnames(locus_data), value = TRUE) locus_data %>% select(Genotype, all_of(allele_cols)) %>% # 宽表转长表,筛选个体携带的等位基因(值为1的项) pivot_longer(-Genotype, names_to = "allele", values_to = "present") %>% filter(present == 1) %>% # 提取等位基因后缀(a/b/c) mutate(allele = str_remove(allele, paste0("^", locus_name))) %>% group_by(Genotype) %>% summarise(allele_list = list(allele)) %>% # 纯合子处理:仅1个等位基因时重复一次,匹配二倍体格式 mutate(allele_list = map(allele_list, ~{ if(length(.x) == 1) rep(.x, 2) else .x })) %>% # 将等位基因列表拆分为多列 unnest_wider(allele_list, names_sep = "_") %>% # 重命名列位要求格式 rename_with(~paste0(locus_name, "_", str_remove(.x, "allele_list_")), starts_with("allele_list")) } # 提取所有独立位点(如Locus_1、Locus_2) loci <- unique(str_remove(grep("^Locus_", colnames(df), value = TRUE), "[a-z]$")) # 批量处理所有位点并合并结果 result_df <- map(loci, ~process_locus(df, .x)) %>% reduce(left_join, by = "Genotype") # 查看转换后的数据 print(result_df)
转换结果
# A tibble: 5 × 7 Genotype Locus_1_1 Locus_1_2 Locus_1_3 Locus_2_1 Locus_2_2 Locus_2_3 <int> <chr> <chr> <chr> <chr> <chr> <chr> 1 1 b c NA b c NA 2 2 a b NA a b NA 3 3 a c NA a c NA 4 4 a b c b c NA 5 5 a a NA b b NA
内容的提问来源于stack exchange,提问作者Josh
相关产品推荐
相关产品推荐

