R语言中比较DataFrame成对列并生成Status列的更优方案咨询
R语言配对列比较生成状态列的优化实现
原始数据结构
你提供的示例数据框结构如下:
df <- structure(list(`chr1:110363793:G:C_A1` = c("1", "2", "2", "2" ), `chr1:110363793:G:C_A2` = c("2", "1", "2", "2"), `chr1:110363823:A:G_A1` = c("2", "2", "2", "2"), `chr1:110363823:A:G_A2` = c("2", "2", "2", "2" ), `chr1:110363849:A:G_A1` = c("2", "2", "2", "2"), `chr1:110363849:A:G_A2` = c("2", "2", "1", "2")), row.names = c("4_653_99", "4_677_99", "25_9_172", "27_135_62706"), class = "data.frame")
需求说明
列名按照「公共前缀+_A1/_A2」成对出现,对每一对列逐行比较:
- 两行值相同,对应Status列赋值为0
- 两行值不同,对应Status列赋值为1
- 新增Status列命名规则为「公共前缀_Status」
现有for循环实现
你当前使用的for循环方案如下:
vars <- unique(sapply(strsplit(colnames(df),"_"), `[`, 1)) for (i in 1:length(vars)){ df[, paste(vars[i], "Status", sep = "_")] <- as.numeric(df[,paste0(vars[i], "_A1")]!=df[,paste0(vars[i], "_A2")]) }
更优实现方案
方案1:纯base R向量化实现(无第三方依赖,性能最优)
直接利用数据框的批量比较特性,完全避免显式循环,代码更精简,运行效率远高于for循环,尤其适合大样本量场景:
# 匹配所有_A1结尾的列,提取公共前缀,生成对应_A2列和Status列名 a1_cols <- grep("_A1$", colnames(df), value = TRUE) prefixes <- sub("_A1$", "", a1_cols) a2_cols <- paste0(prefixes, "_A2") status_cols <- paste0(prefixes, "_Status") # 批量比较直接赋值 df[status_cols] <- as.numeric(df[a1_cols] != df[a2_cols])
方案2:tidyverse实现(可读性更强,易维护)
如果你的项目已经在使用tidyverse生态,可以用dplyr的across语法实现,逻辑更直观:
library(dplyr) library(stringr) df <- df %>% mutate(across(ends_with("_A1"), ~as.numeric(.x != get(str_replace(cur_column(), "_A1$", "_A2"))), .names = "{str_remove(.col, '_A1$')}_Status"))
两种方案输出的结果和你预期的完全一致。
内容的提问来源于stack exchange,提问作者Achal Neupane
相关产品推荐
相关产品推荐

