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

7

我做以下操作

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]

对于真实数据,处理dt(10M行)并创建split_res(18M行)需要大约1小时的时间。

出于好奇 - 是否有加速处理的方法?也许unlist + str_split不是正确的处理方式?


请发布最少的样本数据。 - Dieter Menne
你现在的 "string_column" 变量中存在重复的值。这是应该的吗? - A5C1D2H2I1M1N2O1R2T1
不,抱歉,需要唯一的行(去掉 replace = TRUE) - RInatM
1个回答

15

如果你放弃使用 "stringr" 包中的 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()返回的结果不同,这是因为你在"string_column"中有重复的值。如果您添加一个"id"列并执行相同的操作,您将得到相同的结果。


谢谢,我的情况是加速了十倍 - 以前是3660秒,现在是370秒。 - RInatM

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接