使用dplyr的mutate与ifelse时无法保留NO_HIT列原始值问题
问题解决:按条件更新列同时保留原始有效值
问题背景
需求:当MAYBE列的值为1时,将NO HIT列赋值为1;其他情况保留NO HIT列的原始值。
原始数据表:
GCA_id family `NO HIT` MAYBE HIT <chr> <chr> <dbl> <dbl> <dbl> GCA_000091205.1 Cyanidiaceae 1 NA NA GCA_000341285.1 Cyanidiaceae NA 1 NA GCA_000350225.2 Gigartinaceae NA 1 NA GCA_000372725.1 Noelaerhabdaceae 1 NA NA GCA_002049455.2 Bangiaceae 1 NA NA GCA_002049455.2 Bangiaceae NA 1 1 GCA_002205965.3 Solieriaceae NA 1 1
执行以下代码后,NO HIT列的原始有效值被替换为NA,不符合预期:
table %>% mutate(`NO HIT` = ifelse(MAYBE == 1, 1, `NO HIT`))
错误结果:
GCA_id family `NO HIT` MAYBE HIT <chr> <chr> <dbl> <dbl> <dbl> GCA_000091205.1 Cyanidiaceae NA NA NA GCA_000341285.1 Cyanidiaceae 1 1 NA GCA_000350225.2 Gigartinaceae 1 1 NA GCA_000372725.1 Noelaerhabdaceae NA NA NA GCA_002049455.2 Bangiaceae NA NA NA GCA_002049455.2 Bangiaceae 1 1 1 GCA_002205965.3 Solieriaceae 1 1 1
问题原因
base::ifelse的特性:当测试条件(MAYBE == 1)的结果为NA时,会直接返回NA,忽略else分支的原始值。因此MAYBE为NA的行,哪怕NO HIT原本是有效值,也会被替换成NA。
解决方案
方案1:用%in%替代==处理NA
%in%对NA的判断结果为FALSE而非NA,因此可以避免覆盖原始有效值:
table %>% mutate(`NO HIT` = ifelse(MAYBE %in% 1, 1, `NO HIT`))
方案2:使用dplyr::case_when
case_when仅匹配符合条件的行,未匹配的行自动保留原始值,无需额外处理NA:
table %>% mutate(`NO HIT` = case_when(MAYBE == 1 ~ 1, TRUE ~ `NO HIT`))
方案3:使用dplyr::if_else并指定missing参数
if_else的missing参数可以定义条件为NA时的返回值,直接设置为原始列值即可:
table %>% mutate(`NO HIT` = if_else(MAYBE == 1, 1, `NO HIT`, missing = `NO HIT`))
预期结果
执行任意一种方案后,可得到符合需求的结果:
GCA_id family `NO HIT` MAYBE HIT <chr> <chr> <dbl> <dbl> <dbl> GCA_000091205.1 Cyanidiaceae 1 NA NA GCA_000341285.1 Cyanidiaceae 1 1 NA GCA_000350225.2 Gigartinaceae 1 1 NA GCA_000372725.1 Noelaerhabdaceae 1 NA NA GCA_002049455.2 Bangiaceae 1 NA NA GCA_002049455.2 Bangiaceae 1 1 1 GCA_002205965.3 Solieriaceae 1 1 1
内容的提问来源于stack exchange,提问作者amk
相关产品推荐
相关产品推荐

