使用grepl更快地解决条件嵌套循环

时间:2020-05-01 08:06:16

标签: r performance

我有一个数据集和两个向量。向量“ A”是带有模式的向量,向量“ B”是带有替换的向量。 我想查看数据表(dt)中的Col2,检查它在矢量“ A”中的模式是否正确。如果是这样,将其替换“ B”写入Col4。

为此,我编写了以下代码:

A <- c("AA", "BBB", "CCC", "DDD")
B <- c("PP","QQQ", "I", "Beep")
A <- paste("\\<",A, "\\>", sep = "")


  dt <- structure(list(Col1 = c(0L, 2L, 3L, 5L), Col2 = c("RR,BBB", 
     "S,AA", "FOO", "C"), Col3 = c(1L, 8L, 4L, 2L)), row.names = 
         c(NA, -4L), class = "data.frame")


for (i in 1:length(A)){
  for(j in 1:nrow(dt)){
    if(grepl(A[i], dt[j,2])){
      dt[j,4] <- B[i]
    }      
  }
}

This script works with the following result:

 Col1      Col2    Col3   Col4
  0     "RR,BBB"    1     "CCC"
  2      "S,AA"     8     "PP"
  3      "FOO"      4     <NA>
  5       "C"       2     <NA>

但是,由于数据集大约有400.000行,并且模式和替换矢量成千上万,因此运行需要很长时间。我该如何重写此代码,使其更有效?

1 个答案:

答案 0 :(得分:1)

由于您要替换完整的字符串,因此我认为您需要使用其他模式。

A <- paste0('.*', A, '.*')

然后可以使用向量化的str_replace_all

names(B) <- A
dt$Col4 <- stringr::str_replace_all(dt$Col2, B)

但是如果没有找到模式,它将字符串原样保留,而您想将它们变成NA,这样:

dt$Col4[dt$Col2 == dt$Col4] <- NA
dt

#  Col1     Col2 Col3 Col4
#1    0 R por ke    1  chi
#2    2 Zoom,bee    8   aa
#3    3    om ie    4 <NA>
#4    5      vor    2   ky

数据

dt <- structure(list(Col1 = c(0L, 2L, 3L, 5L), Col2 = c("R por ke", 
"Zoom,bee", "om ie", "vor"), Col3 = c(1L, 8L, 4L, 2L)), row.names = c(NA, 
-4L), class = "data.frame")
A <- c("bee", "por", "fa", "vor")
B <- c("aa","chi", "sti", "ky")