将R中的数据表中的文本列拆分为参差不齐的多个新列
我有一个包含20000多行和一列的数据表。每列中的字符串具有不同的字数。我想把这些单词分开,并把它们放在一个新的列中。我知道如何逐字逐句地做:将R中的数据表中的文本列拆分为参差不齐的多个新列,r,data.table,multiple-columns,strsplit,ragged,R,Data.table,Multiple Columns,Strsplit,Ragged,我有一个包含20000多行和一列的数据表。每列中的字符串具有不同的字数。我想把这些单词分开,并把它们放在一个新的列中。我知道如何逐字逐句地做: Data [ , Word1 := as.character(lapply(strsplit(as.character(Data$complaint), split=" "), "[", 1))] (Data是我的数据表,complaint是列的名称) 显然,这是没有效率的,因为每行中的每个单元格都有不同的字数 你能告诉我一种更有效的方法吗?一个示例数
Data [ , Word1 := as.character(lapply(strsplit(as.character(Data$complaint), split=" "), "[", 1))]
(Data
是我的数据表,complaint
是列的名称)
显然,这是没有效率的,因为每行中的每个单元格都有不同的字数
你能告诉我一种更有效的方法吗?一个示例数据会很好,但是如果我理解你想要什么,就不可能在数据框中正确地执行。鉴于每行中有不同数量的单词,您需要一个列表。尽管如此,在整个对象中分割单词是非常简单的
如果运行
strsplit(as.character(Data[,1]),“”)
将得到一个列表,其中每个元素对应于数据帧中的一行。因此,有几种不同的方法可以重新排列此对象,但最佳方法取决于您的目标,即data.table和data.frame的OK
# toy data
df <- structure(list(x = structure(c(2L, 1L), .Label = c("This actually is not",
"This is interesting"), class = "factor")), .Names = "x", row.names = c(NA,
-2L), class = "data.frame")
# x
# 1 This is interesting
# 2 This actually is not
# the code
split_result <- strsplit(as.character(df$x), " ")
length_n <- sapply(split_result, length)
length_max <- seq_len(max(length_n))
as.data.frame(t(sapply(split_result, "[", i = length_max))) # Or as.data.table(...)
# V1 V2 V3 V4
# 1 This is interesting <NA>
# 2 This actually is not
玩具数据
df这里是一个基于
plyr
包中的rbind.fill.matrix(…)
的解决方案。在一个有20000行的数据集上,它运行大约3.6秒
# create an sample dataset - you have this already
library(data.table)
words <- LETTERS[1:10] # "words" are just letters in this example
set.seed(1) # for reproducible example
w <- sapply(1:2e4,function(i)paste(words[sample(1:10,sample(1:10,1))],collapse=" "))
dt <- data.table(words=w)
head(dt)
# complaint
# 1: D F H
# 2: I J F
# 3: A B I E C D H
# 4: J D G H B I A E
# 5: A D G C
# 6: F E B J I
# you start here...
library(plyr)
result <- rbind.fill.matrix(lapply(strsplit(dt$words, split=" "),matrix,nr=1))
result <- as.data.table(result)
head(result)
# 1 2 3 4 5 6 7 8 9 10
# 1: D F H NA NA NA NA NA NA NA
# 2: I J F NA NA NA NA NA NA NA
# 3: A B I E C D H NA NA NA
# 4: J D G H B I A E NA NA
# 5: A D G C NA NA NA NA NA NA
# 6: F E B J I NA NA NA NA NA
#创建一个示例数据集-您已经有了它
库(数据表)
单词从我的“splitstackshape”软件包中检出cSplit
。它在data.frame
s或data.table
s上工作(但总是返回data.table
)
假设KFB的样本数据至少略微代表您的实际数据,您可以尝试:
library(splitstackshape)
cSplit(df, "x", " ")
# x_1 x_2 x_3 x_4
# 1: This is interesting NA
# 2: This actually is not
另一个(blazing)选项是使用stri_split_fixed
和simplify=TRUE
(来自“stringi”)(这显然被认为很快就进入了“splitstackshape”代码):
自CRAN上的1.9.6版起,有两个功能和可用
有了这一点,我们可以做到:
require(data.table)
setDT(tstrsplit(as.character(df$x), " ", fixed=TRUE))[]
# V1 V2 V3 V4
# 1: This is interesting NA
# 2: This actually is not
tstrsplit
是转置(strsplit(…)
的包装器,我想是时候抛弃rbind.fill.matrix了。您是否已从“stringi”软件包中看到stri_list2matrix
?试试:stri_list2matrix(strsplit(dt$words,split=“”),byrow=TRUE)
。您的时间将从3秒以上下降到<0.2秒…@AnandaMahto Yes。它似乎比cSplit(…)快
,但比stri\u split\u fixed(…)慢。请参见上面的基准测试结果。@jihoward,因此我对该方法在不久的将来被包含在“splitstackshape”中的评论:-)我只是在等待“stringi”0.3-1出现在CRAN上,现在是这样,所以我需要重写一些现有函数….+1用于基准测试:-),如果您添加了fixed=TRUE
,则strsplit至少会有一点提升。但不确定这会对基准测试产生多大影响。在某些情况下,简单strsplit似乎比上面提出的cSplit更快。Tstrsplit可能值得一试。
library(stringi)
stri_split_fixed(df$x, " ", simplify = TRUE)
# [,1] [,2] [,3] [,4]
# [1,] "This" "is" "interesting" NA
# [2,] "This" "actually" "is" "not"
require(data.table)
setDT(tstrsplit(as.character(df$x), " ", fixed=TRUE))[]
# V1 V2 V3 V4
# 1: This is interesting NA
# 2: This actually is not