Быстрый способ разбить строку и преобразовать в длинный формат в data.table

Я делаю следующее

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 ответ

Решение

Вы получите большое ускорение, если просто бросите str_split() от "stringr" и просто использовать 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" и сделаете то же самое, вы получите те же результаты.

Другие вопросы по тегам