在data.table列中分割文本string
我有一个脚本,它将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 +行,所以时间/内存效率变得非常重要。
更新:
在Frank的build议之后,我创build了一个更大的testing用例,并使用了build议的命令,但是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倍的时间。
更新:从版本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 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()
和?transpose()
。
查看旧的答案的历史。
我为没有使用data.table
人添加了答案,也希望有一个单行的解决scheme。
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
用tidyr解决scheme是:
separate(df,col = "PREFIX",into = c("PX", "PY"), sep = "_")