在dplyr的mutate中基于行值处理时,grepl可用但str_detect无法得到预期结果的原因?
在dplyr的mutate中基于行值处理时,grepl可用但str_detect无法得到预期结果的原因?
嗨,这个问题的核心其实是str_detect和grepl对NA值的处理逻辑不一样,咱们一步步拆解来看:
1. 两个函数对NA的处理差异
这是最关键的区别:
- 来自stringr包的
str_detect:当输入的字符串是NA时,它会直接返回NA,不会转换成逻辑值TRUE/FALSE。 - base R的
grepl:遇到NA输入时,会默认返回FALSE,这是base R字符串处理函数的常见行为。
2. 结合if_else的行为导致结果不同
if_else是一个严格的条件判断函数,它要求条件必须是明确的TRUE或FALSE:
- 当你用
str_detect时,error列是NA的行,条件会返回NA,if_else不会执行任何分支,直接把NA作为date_corr的结果——这就是你看到那些NA行的date_corr变成NA的原因。 - 而用
grepl时,error为NA的行条件返回FALSE,if_else会执行else分支,把原date的值赋值给date_corr,这正好符合你的预期。
3. 让str_detect达到预期效果的解决办法
你只需要把str_detect返回的NA转换成FALSE,或者换用更灵活的case_when:
方法一:用replace_na处理NA值
library(tidyr) # 需要加载tidyr包来用replace_na test %>% mutate(date_corr = if_else( str_detect(error, "date \\= 01\\.03\\.2022$") %>% replace_na(FALSE), as.Date('2022/03/01'), date ), date_corr = if_else( str_detect(error, "date \\= 01\\.05\\.2021$") %>% replace_na(FALSE), as.Date('2021/05/01'), date_corr ))
方法二:用case_when更优雅地处理多条件
case_when会自动处理NA的情况,当前面的条件都不匹配(包括条件为NA)时,会匹配最后一个TRUE分支:
test %>% mutate(date_corr = case_when( str_detect(error, "date \\= 01\\.03\\.2022$") ~ as.Date('2022/03/01'), str_detect(error, "date \\= 01\\.05\\.2021$") ~ as.Date('2021/05/01'), TRUE ~ date # 所有不满足前面条件的情况(包括error为NA)都保留原日期 ))
这两种方法都能得到和grepl版本完全一致的结果,同时保留str_detect在大数据集上的性能优势。
备注:内容来源于stack exchange,提问作者filcfig
相关产品推荐
相关产品推荐

