R语言中比较dataframe两列,将相同值对应val2替换为NA的实现问题
问题:替换DataFrame中与val1完全匹配的val2值为NA
我有一个包含4列的DataFrame,需要比较val1和val2列,当两列数值内容完全相同时,将val2对应位置的值替换为NA。注意:若两列数值不同(如示例第三行val1为123、val2为1236),则保留val2原有值。
数据示例
实际数据
structure(list(record_id = c(1L, 2L, 2L, 3L, 4L, 5L), name = c("CDK19", "DYNC1H1", "G6PD", "NPRL2", "CHD2", "LGI1"), val1 = c("c.386A>C", "c.G5864T", "c.T1058C", "c.323_339+19del", "c.2876+3_2876+6delAAGT", "c.757G>A"), val2 = c(NA, "c.5864G>T", NA, "c.323_339+19del", "c.2876+3_2876+6delAAGT", "c.757G>A")), row.names = c(NA, -6L ), class = c("tbl_df", "tbl", "data.frame"))
虚拟数据
# rec_id name val1 val2 # 1 abby g.B123C g.123B>C # 1 Amy g.B183C g.123B>C # 2 abby g.B123C g.1236B>C # 3 Amy g.2876+3_2876+6delABC g.2876+3_2876+6delABC # 4 Amber g.2876+3_2876+6delABC g.2876+3_2876+6delABC # 5 Axe g.2876G>C NA
期望输出
# rec_id name val1 val2 # 1 abby g.B123C NA # 1 Amy g.B183C g.123B>C # 2 abby g.B123C g.1236B>C # 3 Amy g.2876+3_2876+6delABC NA # 4 Amber g.2876+3_2876+6delABC NA # 5 Axe g.2876+g>c NA
尝试的错误代码
mydata %>% for (i in 1:nrow(mydata)) { if (mydata$val1[i] == mydata$val2[i]) { mydata$val2[i] <- NA } }
问题说明:管道符%>%后不能直接接for循环,管道符的作用是将左侧数据传递给右侧的函数,循环不属于函数式操作,因此这段代码无法运行。
正确解决方案
方法1:使用dplyr(tidyverse风格)
利用mutate结合ifelse,同时处理NA值的情况(NA与任何值比较结果都是NA,需要先判断两列都不为NA再比较):
library(dplyr) mydata_processed <- mydata %>% mutate(val2 = ifelse(!is.na(val1) & !is.na(val2) & val1 == val2, NA, val2))
方法2:基础R方式
直接通过索引赋值,无需加载额外包:
# 找到val1和val2都非NA且相等的行索引 match_idx <- !is.na(mydata$val1) & !is.na(mydata$val2) & mydata$val1 == mydata$val2 # 将对应行的val2设为NA mydata$val2[match_idx] <- NA
测试补充数据
针对给出的df2和df3,上述代码均可正常处理:
df2中val2全为NA,处理后无变化df3中无val1与val2完全匹配的行,处理后val2保持原样
内容的提问来源于stack exchange,提问作者akang
相关产品推荐
相关产品推荐

