Разделить текстовую строку в столбцах data.table

У меня есть сценарий, который считывает данные из файла CSV в data.table а затем разбивает текст в одном столбце на несколько новых столбцов. В настоящее время я использую функции lapply и strsplit для этого. Вот пример:

 library("data.table") df = data.table(PREFIX = c("A_B","A_C","A_D","B_A","B_C","B_D"), VALUE = 1:6) dt = as.data.table(df) # split PREFIX into new columns dt$PX = as.character(lapply(strsplit(as.character(dt$PREFIX), split="_"), "[", 1)) dt$PY = as.character(lapply(strsplit(as.character(dt$PREFIX), split="_"), "[", 2)) dt # PREFIX VALUE PX PY # 1: A_B 1 AB # 2: A_C 2 AC # 3: A_D 3 AD # 4: B_A 4 BA # 5: B_C 5 BC # 6: B_D 6 BD 

В приведенном выше примере столбец PREFIX разбивается на два новых столбца PX и PY на символ «_».

Хотя это работает отлично, мне было интересно, есть ли лучший (более эффективный) способ сделать это, используя data.table . Мои реальные наборы данных имеют> = 10M + строк, поэтому эффективность времени / памяти становится действительно важной.


ОБНОВИТЬ:

Следуя предложению Фрэнка, я создал более крупный тестовый пример и использовал предложенные команды, но stringr::str_split_fixed занимает намного больше времени, чем исходный метод.

 library("data.table") library("stringr") system.time ({ df = data.table(PREFIX = rep(c("A_B","A_C","A_D","B_A","B_C","B_D"), 1000000), VALUE = rep(1:6, 1000000)) dt = data.table(df) }) # user system elapsed # 0.682 0.075 0.758 system.time({ dt[, c("PX","PY") := data.table(str_split_fixed(PREFIX,"_",2))] }) # user system elapsed # 738.283 3.103 741.674 rm(dt) system.time ( { df = data.table(PREFIX = rep(c("A_B","A_C","A_D","B_A","B_C","B_D"), 1000000), VALUE = rep(1:6, 1000000) ) dt = as.data.table(df) }) # user system elapsed # 0.123 0.000 0.123 # split PREFIX into new columns system.time ({ dt$PX = as.character(lapply(strsplit(as.character(dt$PREFIX), split="_"), "[", 1)) dt$PY = as.character(lapply(strsplit(as.character(dt$PREFIX), split="_"), "[", 2)) }) # user system elapsed # 33.185 0.000 33.191 

Поэтому метод str_split_fixed занимает примерно 20X раз.

Обновление. Начиная с версии 1.9.6 (по CRAN с сентября 15), мы можем использовать функцию tstrsplit() чтобы получить результаты напрямую (и более эффективным образом):

 require(data.table) ## v1.9.6+ dt[, c("PX", "PY") := tstrsplit(PREFIX, "_", fixed=TRUE)] # PREFIX VALUE PX PY # 1: A_B 1 AB # 2: A_C 2 AC # 3: A_D 3 AD # 4: B_A 4 BA # 5: B_C 5 BC # 6: B_D 6 BD 

tstrsplit() основном представляет собой оболочку для transpose(strsplit()) , где функция transpose() , также недавно реализованная, переносит список. ?tstrsplit() см. Здесь ?tstrsplit() и ?tstrsplit() .

См. Историю старых ответов.

Я добавляю ответ для тех, кто не использует data.table v1.9.5, а также хочет однострочное решение.

 dt[, c('PX','PY') := do.call(Map, c(f = c, strsplit(PREFIX, '-'))) ] 

Использование пакета splitstackshape :

 library(splitstackshape) cSplit(df, splitCols = "PREFIX", sep = "_", direction = "wide", drop = FALSE) # PREFIX VALUE PREFIX_1 PREFIX_2 # 1: A_B 1 AB # 2: A_C 2 AC # 3: A_D 3 AD # 4: B_A 4 BA # 5: B_C 5 BC # 6: B_D 6 BD 

С тидиром решение:

 separate(df,col = "PREFIX",into = c("PX", "PY"), sep = "_") 
  • Упрощенная пирамида наseleniumия в ggplot2
  • Расчет скользящей средней
  • Элегантное назначение нескольких столбцов в data.table с помощью lapply ()
  • Таблица взаимодействий - случай с домашними животными и домами
  • Воспроизведение решеточного диаграммы дендрограммы с ggplot2
  • Используя grep в R, чтобы найти строки как целые слова (но не строки как часть слов)
  • Как объединить два кадра данных на основе двух столбцов?
  • Collapse / concatenate / aggregate column для отдельной строки, разделенной запятой, в каждой группе
  • Как получить максимальное значение по группе
  • Использование распространения с повторяющимися идентификаторами для строк
  • Как эффективно внедряться в R
  • Давайте будем гением компьютера.