Разделить текстовую строку в столбцах 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 + строк, поэтому эффективность времени / памяти становится действительно важной.
- Разделите строки с разделителями в столбце и вставьте в качестве новых строк
- Графические диаграммы на карте с использованием ggplot2?
- Что такое аргумент width в position_dodge?
- Что такое целочисленное переполнение в R и как это может произойти?
- Создание многострочной диаграммы для нескольких переменных - ggplot2 в R
ОБНОВИТЬ:
Следуя предложению Фрэнка, я создал более крупный тестовый пример и использовал предложенные команды, но 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 раз.
- Проблема при передаче переменной с обозначением знака доллара ($) на aes () в сочетании с facet_grid () или facet_wrap ()
- Ошибка в : объект типа «закрытие» не является подмножеством
- Объединение двух фреймов данных с использованием нечеткого / приближенного соответствия строк в R
- Как можно наложить эллипс данных на диаграмму рассеяния ggplot2?
- Матричная версия cor.test ()
- Как сравнить функции?
- ggplot2, facet_grid, свободные шкалы?
- Почему as.factor возвращает символ при использовании внутри приложения?
Обновление. Начиная с версии 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 = "_")