快速分割字符串并在data.table中转换为长格式

时间:2014-03-27 04:20:34

标签: r substring data.table data-manipulation

我做以下

library(data.table)
library(stringr)        
dt <- data.table(string_column = paste(sample(c(letters, " "), 500000, replace = TRUE)
                                     , sample(c(letters, " "), 500000, replace = TRUE)
                                     , sample(1:500000)
                                 , sep = " "), key = "string_column") 

split_res <- dt[, list(name = unlist(str_split(string_column, '\\s+'))), by = string_column]

对于实际数据,需要大约。 1小时处理dt(10M行)并创建split_res(18M行) 出于好奇 - 有没有办法加快进程?也许unlist + str_split不是正确的做法吗?

1 个答案:

答案 0 :(得分:11)

如果您只是使用来自&#34; stringr&#34;的str_split(),您将获得更大的加速。并使用strsplit()

fun1 <- function() dt[, list(name = unlist(str_split(string_column, '\\s+'))), by = string_column]
fun2 <- function() dt[, list(name = unlist(strsplit(string_column, '\\s+'))), by = string_column]

system.time(fun1())
#    user  system elapsed 
#  172.41    0.05  172.82 

system.time(fun2())
#    user  system elapsed 
#   11.22    0.01   11.23 

这是否会使您的处理时间从一小时缩短到4分钟,我不确定。但至少你不必记得在你的函数名称中加入那些令人讨厌的下划线: - )


如果您可以拆分固定搜索模式,则可以使用fixed = TRUE参数,这将为您提供另一个显着的速度提升。


要考虑的另一件事是手动完成这个过程:

x <- strsplit(dt$string_column, "\\s+")
DT <- dt[rep(sequence(nrow(dt)), vapply(x, length, 1L))]
DT[, name := unlist(x, use.names = FALSE)]
DT

使用您的样本数据:

fun4 <- function() {
  x <- strsplit(dt$string_column, "\\s+")
  DT <- dt[rep(sequence(nrow(dt)), vapply(x, length, 1L))]
  DT[, name := unlist(x, use.names = FALSE)]
  DT
}
#    user  system elapsed 
#    1.79    0.01    1.82

然而,答案与fun2()的答案不同,但那是因为你在&#34; string_column&#34;中有重复的值。如果你添加一个&#34; id&#34;列并做同样的事情,你会得到相同的结果。