r - 为什么 grepl 可以工作但 str_detect 不能根据行值进行变异?

标签 r stringr grepl

我一直在努力解决这个问题。

我需要根据在我的数据库中另一个“错误”列中检测到的特定评论来创建一个更正的列。我可以使用 grepl 解决这个问题,但我正在努力让 str_detect 也能正常工作(对于大数据集,它通常更快)。

这是一个示例数据库:

test <- tibble(
  id = seq(1:30),
  date = sample(seq(as.Date('2000/01/01'), as.Date('2018/01/01'), by="day"), 30),
  error = c(rep(NA, 3), "wrong date! Correct date = 01.03.2022",
            rep(NA, 5), "wrong date! Correct date = 01.05.2021",
            rep(NA, 5), "wrong date! Correct date = 01.03.2022",
            rep(NA, 7), "wrong date! Correct date = 01.05.2021",
            rep(NA, 2), "date already corrected on 01.05.2021",
            NA, "date already corrected on 01.03.2022", NA))

我首先尝试使用 str_detect 创建一个新的“date_corr”列:

test %>%
  mutate(date_corr=if_else(str_detect(error, "date \\= 01\\.03\\.2022$"), as.Date('2022/03/01'), date),
         date_corr=if_else(str_detect(error, "date \\= 01\\.05\\.2021$"), as.Date('2021/05/01'), date_corr))

这会产生:

A tibble: 30 × 4
      id date       error                                 date_corr 
   <int> <date>     <chr>                                 <date>    
 1     1 2010-04-28 NA                                    NA        
 2     2 2004-06-30 NA                                    NA        
 3     3 2015-09-25 NA                                    NA        
 4     4 2005-08-21 wrong date! Correct date = 01.03.2022 2022-03-01
 5     5 2008-07-16 NA                                    NA        
 6     6 2004-08-02 NA                                    NA        
 7     7 2001-10-15 NA                                    NA        
 8     8 2007-07-21 NA                                    NA        
 9     9 2014-04-19 NA                                    NA        
10    10 2013-02-08 wrong date! Correct date = 01.05.2021 2021-05-01
# … with 20 more rows

按行添加是无关紧要的:

test %>%
  rowwise() %>%
  mutate(date_corr=if_else(str_detect(error, "date \\= 01\\.03\\.2022$"), as.Date('2022/03/01'), date),
         date_corr=if_else(str_detect(error, "date \\= 01\\.05\\.2021$"), as.Date('2021/05/01'), date_corr))

A tibble: 30 × 4
# Rowwise: 
      id date       error                                 date_corr 
   <int> <date>     <chr>                                 <date>    
 1     1 2010-04-28 NA                                    NA        
 2     2 2004-06-30 NA                                    NA        
 3     3 2015-09-25 NA                                    NA        
 4     4 2005-08-21 wrong date! Correct date = 01.03.2022 2022-03-01
 5     5 2008-07-16 NA                                    NA        
 6     6 2004-08-02 NA                                    NA        
 7     7 2001-10-15 NA                                    NA        
 8     8 2007-07-21 NA                                    NA        
 9     9 2014-04-19 NA                                    NA        
10    10 2013-02-08 wrong date! Correct date = 01.05.2021 2021-05-01
# … with 20 more rows

但是,无论按行如何,使用 grepl 我都能得到想要的结果:

test %>%
  mutate(date_corr=if_else(grepl("date \\= 01\\.03\\.2022$", error), as.Date('2022/03/01'), date),
         date_corr=if_else(grepl("date \\= 01\\.05\\.2021$", error), as.Date('2021/05/01'), date_corr))

# A tibble: 30 × 4
      id date       error                                 date_corr 
   <int> <date>     <chr>                                 <date>    
 1     1 2010-04-28 NA                                    2010-04-28
 2     2 2004-06-30 NA                                    2004-06-30
 3     3 2015-09-25 NA                                    2015-09-25
 4     4 2005-08-21 wrong date! Correct date = 01.03.2022 2022-03-01
 5     5 2008-07-16 NA                                    2008-07-16
 6     6 2004-08-02 NA                                    2004-08-02
 7     7 2001-10-15 NA                                    2001-10-15
 8     8 2007-07-21 NA                                    2007-07-21
 9     9 2014-04-19 NA                                    2014-04-19
10    10 2013-02-08 wrong date! Correct date = 01.05.2021 2021-05-01
# … with 20 more rows

test %>%
  rowwise() %>%
  mutate(date_corr=if_else(grepl("date \\= 01\\.03\\.2022$", error), as.Date('2022/03/01'), date),
         date_corr=if_else(grepl("date \\= 01\\.05\\.2021$", error), as.Date('2021/05/01'), date_corr))

A tibble: 30 × 4
# Rowwise: 
      id date       error                                 date_corr 
   <int> <date>     <chr>                                 <date>    
 1     1 2010-04-28 NA                                    2010-04-28
 2     2 2004-06-30 NA                                    2004-06-30
 3     3 2015-09-25 NA                                    2015-09-25
 4     4 2005-08-21 wrong date! Correct date = 01.03.2022 2022-03-01
 5     5 2008-07-16 NA                                    2008-07-16
 6     6 2004-08-02 NA                                    2004-08-02
 7     7 2001-10-15 NA                                    2001-10-15
 8     8 2007-07-21 NA                                    2007-07-21
 9     9 2014-04-19 NA                                    2014-04-19
10    10 2013-02-08 wrong date! Correct date = 01.05.2021 2021-05-01
# … with 20 more rows

我在这里缺少什么?

最佳答案

区别在于它们处理 NA 值的方式

str_detect(NA, "missing")
# [1] NA
grepl("missing", NA)
# [1] FALSE

请注意,如果您在 if_else 的条件中有一个 NA 值,它也会保留 NA

if_else(NA, 1, 2)
# [1] NA

str_detect 保留了 NA 值。目前尚不清楚“正确”的值(value)应该是什么。但是,如果您希望 str_detect 具有与 grepl 相同的值,您可以明确表示不更改 NA 值

test %>%
  mutate(date_corr=if_else(!is.na(error) & str_detect(error, "date \\= 01\\.03\\.2022$"), as.Date('2022/03/01'), date),
         date_corr=if_else(!is.na(error) & str_detect(error, "date \\= 01\\.05\\.2021$"), as.Date('2021/05/01'), date_corr))

关于r - 为什么 grepl 可以工作但 str_detect 不能根据行值进行变异?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75412749/

相关文章:

r - 在 Mac/Linux 上从 R 连接到 MS SQL Server

r - 从字符串中选择第n个字符

r - StringsR - 捕获正确的数字

r - 在一条线段上,找到沿线 x 个单位的点

r - RStudio 中的半透明

正则表达式、R 和逗号

r - filter() 和 str_detect() 时找不到列对象

r - 将角色分成几部分

r - 通过连续的冒号从字符串中提取字符

r - 每隔一行拆分变量以在 data.frame 中形成两个新列