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



у меня есть скрипт, который считывает данные из 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 A B
# 2: A_C 2 A C
# 3: A_D 3 A D
# 4: B_A 4 B A
# 5: B_C 5 B C
# 6: B_D 6 B D


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



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





обновление:



следуя предложению @ Frank Я создал более крупный тестовый случай и использовал предложенные команды, но 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 метод занимает около 20 раз больше времени.

497   5  
r

5 ответов:

обновление: из версии 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  A  B
# 2:    A_C     2  A  C
# 3:    A_D     3  A  D
# 4:    B_A     4  B  A
# 5:    B_C     5  B  C
# 6:    B_D     6  B  D

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

смотрите историю для старых ответов.

Я добавляю ответ для тех, кто не использует data.tableВ1.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        A        B
# 2:    A_C     2        A        C
# 3:    A_D     3        A        D
# 4:    B_A     4        B        A
# 5:    B_C     5        B        C
# 6:    B_D     6        B        D

С tidyr решение:

separate(df,col = "PREFIX",into = c("PX", "PY"), sep = "_")

о чем ??? fread (text = DT$PREFIX )

Comments

    Ничего не найдено.