如何在R中用for循环遍历两数据框列名并输出匹配结果?
批量比较两个数据集对应列的匹配情况
问题背景
有两个列名相同的数据集,需基于sample_ID比较对应loci列的数据,为每个loci生成标注match或no_match的新列。示例数据如下:
df1 <- data.frame(sample_ID = c('animal1', 'animal2', 'animal3', 'animal4', 'animal5'), loci1 = c('T,T', 'A,T', 'C,T', 'T,T', 'T,G'), loci2 = c('G,T', 'T,T', 'A,T', 'T,T', 'T,A')) df2 <- data.frame(sample_ID = c('animal1', 'animal2', 'animal3', 'animal4', 'animal5'), loci1 = c('T,T', 'A,T', 'C,T', 'A,A', 'C,G'), loci2 = c('T,T', 'T,A', 'T,T', 'T,G', 'T,A'))
已实现单loci列的匹配判断:
df3 <- df1 %>% inner_join(df2, by = 'sample_ID') %>% mutate(match_loci1 = c('no_match', 'match')[1 + (loci1.x == loci1.y)])
但尝试用for循环批量处理时报错:
loci_names <- colnames(df1) test2 <- df1 %>% inner_join(df2, by = 'sample_ID') %>% for (i in loci_list) { mutate(match$[[i]] = c('no_match', 'match')[1 + [[i]]$.x == [[i]]$.y]) }
报错信息:Error: unexpected '[[' in: " for (i in loci_list) { mutate(match$[["
解决方案
方法1:使用dplyr::across(推荐)
利用across批量处理所有loci列,无需循环,代码简洁高效:
library(dplyr) # 获取所有loci列名(排除sample_ID) loci_cols <- setdiff(colnames(df1), "sample_ID") df_result <- df1 %>% inner_join(df2, by = "sample_ID") %>% mutate( across( all_of(loci_cols), ~ case_when( .data[[paste0(cur_column(), ".x")]] == .data[[paste0(cur_column(), ".y")]] ~ "match", TRUE ~ "no_match" ), .names = "match_{.col}" ) )
all_of(loci_cols)指定要处理的目标列.names = "match_{.col}"自动生成规范的新列名(如match_loci1)case_when清晰定义匹配逻辑,比索引向量更易读维护
方法2:修正for循环写法
若坚持使用循环,需调整语法以适配管道逻辑:
loci_cols <- setdiff(colnames(df1), "sample_ID") df_joined <- df1 %>% inner_join(df2, by = "sample_ID") for (col in loci_cols) { df_joined <- df_joined %>% mutate(!!sym(paste0("match_", col)) := c("no_match", "match")[1 + (.data[[paste0(col, ".x")]] == .data[[paste0(col, ".y")]])]) }
!!sym()用于动态生成列名,实现变量到列名的转换.data[[...]]确保在循环中正确引用拼接后的列名
方法3:使用purrr::map
结合purrr的映射函数批量生成匹配结果列:
library(purrr) library(dplyr) loci_cols <- setdiff(colnames(df1), "sample_ID") df_joined <- df1 %>% inner_join(df2, by = "sample_ID") match_cols <- map_dfc(loci_cols, function(col) { df_joined %>% transmute(!!sym(paste0("match_", col)) := if_else(.data[[paste0(col, ".x")]] == .data[[paste0(col, ".y")]], "match", "no_match")) }) df_result <- bind_cols(df_joined, match_cols)
结果说明
处理后的数据框将保留原有的sample_ID、loci1.x、loci1.y等列,同时新增match_loci1、match_loci2等匹配结果列,每个结果列对应原loci列的匹配状态。
内容的提问来源于stack exchange,提问作者Emma Horton
相关产品推荐
相关产品推荐

