R加入like / grep条件

时间:2016-03-15 12:20:03

标签: r join data.table sql-like

我正在寻找使用grep / like / stri_detect条件在字符列上连接2个data.frames / data.tables的有效方法。

我可以使用sqldf包加入类似,但速度很慢。在我的2个data.tables(5k行,20k行)上大约需要60秒。

我的第二种方法是使用data.table中的CJ,然后在2列上使用stri_detect_fixed。这种方法更快(16秒),但我担心随着数据的增长,它将无法使用(它显着增加了ram的使用)。

我也尝试在for循环中进行,但它是最慢的。

有没有办法更快地完成它,尤其是在data.table?

下面我粘贴我的示例:

library(stringi)
library(data.table)
library(sqldf)
data1 <- data.table(col1 = paste0(c("asdasd asdasd 768jjhknmnmnj",
"78967ggh","kl00896754","kl008jku"),1:10000))

data2 <- data.table(col2 = paste0(c("mnj", "12345","kl008","lll1"), 1:10000))

system.time(join1 <- data.table(sqldf("select * 
           from data1 a inner join data2 b
                      on a.col1 like '%' || b.col2 || '%'", drv = "SQLite" )))



system.time(kartezjan <- CJ(col1 = data1[,c("col1"), with = F][[1]],
                            col2 = data2[,c("col2"), with = F][[1]],
 unique  = TRUE)[stri_detect_fixed(col1, col2, case_insensitive = FALSE)])

1 个答案:

答案 0 :(得分:1)

我的机器上localhost:8080/Mr-robot-king 方法对于您的示例数据来说是最快的,但如果它有帮助,这里有一个更快的sqldf版本。

data.table

我在OSX上运行它 - 您可能需要调整其他操作系统的并行化代码。此外,如果您的实际数据较大并且内存不足,则可以尝试更大的library(data.table) library(sqldf) ## Example data v1 <- paste0(c("asdasd asdasd 768jjhknmnmnj", "78967ggh","kl00896754","kl008jku"), 1:10000) v2 <- paste0(c("mnj", "12345","kl008","lll1"), 1:10000) data1 <- data.table(col1=v1, key="col1") data2 <- data.table(col2=v2, key="col2") ## sqldf version system.time( ans1 <- data.table(sqldf( "select * from data1 a inner join data2 b on instr(a.col1, b.col2)", drv="SQLite")) ) ## user system elapsed ## 17.579 0.036 17.654 ## parallelized data.table version suppressMessages(library(foreach)); suppressMessages(library(doParallel)) cores <- detectCores() ## I've got 4... clust <- makeForkCluster(cores) registerDoParallel(clust) system.time({ batches <- cores data2[, group:=sort(rep_len(1:batches, nrow(data2)))] ans2 <- foreach( i=1:batches, .combine=function(...) rbindlist(list(...)), .multicombine=TRUE, .inorder=FALSE) %dopar% { CJ(col1=data1[, col1], col2=data2[group==i, col2])[, alike:=col1 %like% col2, by=col2][ alike==TRUE][, alike:=NULL][] } }) ## user system elapsed ## 0.185 0.229 30.295 stopCluster(clust) stopImplicitCluster() 值。