在R中自适应地将列拆分为多列

时间:2016-02-23 19:31:34

标签: r

我的数据框如下所示:

Name    Value
abc     Asia
def     Asia/Africa
gbc     Africa
jhg     America/Africa/Asia

我想要将列Value分开,以便数据框如下所示:

Name    Value.1    Value.2    Value.3
abc     Asia 
def     Asia       Africa
gbc     Africa
jhg     America    Africa    Asia

我知道stackoverflow上有类似的问题(例如herehere),但他们认为 Value 可以分成每行相同数量的部分。所以,当我尝试运行以下命令时:

out <- strsplit(as.character(df$Value),'/')
do.call(rbind, out)
data.frame(df$Value, do.call(rbind, out))

它一直工作到第二行,然后给我以下错误:

Error in data.frame(df$Value, do.call(rbind,  : 
  arguments imply differing number of rows: 24819, 24707
In addition: Warning message:
In (function (..., deparse.level = 1)  :
  number of columns of result is not a multiple of vector length (arg 10)

我还研究了reshape2函数colSplit和tidyr函数separate。他们还希望,对于每一行, Value 可以分成完全相同数量的组件,因此他们希望我提前命名列。

我想知道有一种方法可以自适应地命名将 Value 分割成名为 Value.1 Value.2 的单独列, ...

3 个答案:

答案 0 :(得分:4)

我们可以使用cSplit

library(splitstackshape)
cSplit(df1, 'Value', '/', 'wide')
#   Name Value_1 Value_2 Value_3
#1:  abc    Asia      NA      NA
#2:  def    Asia  Africa      NA
#3:  gbc  Africa      NA      NA
#4:  jhg America  Africa    Asia

base R中,我们可以简单地执行

cbind(df1[1],read.table(text=df1$Value, sep='/', fill=TRUE))
#  Name      V1     V2   V3
#1  abc    Asia            
#2  def    Asia Africa     
#3  gbc  Africa            
#4  jhg America Africa Asia

答案 1 :(得分:4)

请参阅tstrsplit中的data.table,它会自动填充参差不齐的分割(默认情况下为NA,但可以使用fill参数进行控制):

library(data.table)
setDT(df1)[ , tstrsplit(Value, split = "/")]

如果您想将这些作为列添加到数据中,动态执行会有点麻烦

setDT(df1)[ , paste0("V", 1:max(sapply(spl <- strsplit(x, "/"), length))) := 
              transpose(spl)]

答案 2 :(得分:4)

在基地R:

df <- read.table(textConnection("Name    Value
abc     Asia
def     Asia/Africa
gbc     Africa
jhg     America/Africa/Asia"), header=TRUE)

out <- strsplit(as.character(df$Value),'/')
out <- lapply(out, FUN=function(x) c(unlist(x), rep(NA, max(lengths(out))-length(x))))
out <- as.data.frame( cbind(df$Value,do.call(rbind, out)))

  V1      V2     V3   V4
1  3    Asia   <NA> <NA>
2  4    Asia Africa <NA>
3  1  Africa   <NA> <NA>
4  2 America Africa Asia

相同的方法,写得有点不同:

out <- strsplit(as.character(df$Value),'/')
cbind(df[1], do.call(rbind, lapply(out, 'length<-', max(lengths(out)))))
  Name       1      2    3
1  abc    Asia   <NA> <NA>
2  def    Asia Africa <NA>
3  gbc  Africa   <NA> <NA>
4  jhg America Africa Asia