2014-03-27 1 views
7

Я следующеебыстрый способ разделить строку и преобразовать в длинном формате в 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 - это неправильный способ сделать это?

+0

Просьба указать минимальные данные образца –

+0

У вас есть дублированные значения в текущей переменной "string_column". Если это так? – A5C1D2H2I1M1N2O1R2T1

+0

нет, извините, нужны уникальные ряды (избавился от replace = TRUE) – RInatM

ответ

10

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

+0

Спасибо, в моем случае у меня десятикратное ускорение - было - 3660s, теперь - 370s – RInatM