在data.table列中拆分文本字符串

时间:2013-08-09 19:49:43

标签: r data.table

我有一个脚本可以将CSV文件中的数据读入data.table,然后将一列中的文本拆分为几个新列。我目前正在使用lapplystrsplit函数执行此操作。这是一个例子:

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 

在上面的示例中,{_ 1}列列在“_”字符上分为两个新列PREFIXPX

尽管这很好用,但我想知道是否有更好(更有效)的方法来使用PY来实现这一点。我的真实数据集有> = 10M +行,因此时间/内存效率变得非常重要。


更新

按照@ Frank的建议,我创建了一个更大的测试用例并使用了建议的命令,但data.table比原始方法花了更长的时间。

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 方法需要大约20倍的时间。

5 个答案:

答案 0 :(得分:93)

更新:从版本1.9.6(截至2015年9月的CRAN),我们可以使用函数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()

查看旧答案的历史记录。

答案 1 :(得分:13)

我为不使用data.table v1.9.5 的人添加了答案,并且还想要一行解决方案。

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

答案 2 :(得分:5)

使用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

答案 3 :(得分:0)

使用tidyr,解决方案是:

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

答案 4 :(得分:-1)

那??? fread(text = dt $ PREFIX)