将列拆分为两个具有相同列名的新列

时间:2014-11-17 04:47:14

标签: r

我希望将每列中用逗号分隔的值对分成新数据框中的两个相邻列,并为两个新列中的每一列分配相同的列名。

也就是说,我想转换它:

A   B   C   D   E 
1,1 0,1 1,1 1,1 1,1 
1,1 1,1 1,1 1,1 1,1
0,1 0,1 0,1 0,1 0,1 

到此:

A  A  B  B  C  C  D  D  E  E
1  1  0  1  1  1  1  1  1  1
1  1  1  1  1  1  1  1  1  1
0  1  0  1  0  1  0  1  0  1

如果数据框名称不能完全重复,则A_1和A_2 ......等等应该没问题。或者,将数据框的第一行中的名称替换为标题也可以。

我的实际数据集是大约200列~13,000行,所以我需要一种自动分割列的方法,并为数据框的第二个版本指定名称。

2 个答案:

答案 0 :(得分:7)

您可以使用

library(splitstackshape)
(newdf <- cSplit(df, names(df), ","))
#    A_1 A_2 B_1 B_2 C_1 C_2 D_1 D_2 E_1 E_2
# 1:   1   1   0   1   1   1   1   1   1   1
# 2:   1   1   1   1   1   1   1   1   1   1
# 3:   0   1   0   1   0   1   0   1   0   1

要创建重复的列名称,您可以执行以下操作,因为data.table也加载了splitstackshape

setnames(newdf, names(newdf), sub("_.*", "", names(newdf)))
newdf
#    A A B B C C D D E E
# 1: 1 1 0 1 1 1 1 1 1 1
# 2: 1 1 1 1 1 1 1 1 1 1
# 3: 0 1 0 1 0 1 0 1 0 1

但是你知道,拥有重复的列名是一个糟糕的主意。

答案 1 :(得分:4)

不要把自己踢到这里,但是,随着“stringi”软件包的最新发展,cSplit不再为这类工作做好准备了。

以下是使用Stringi的方法(虽然它特定于问题)。

首先,创建一个分裂函数:

library(stringi)
Stringi <- function(indf) {
  X <- do.call(cbind, lapply(indf, stri_split_fixed, ",", simplify = TRUE))
  `dimnames<-`(`dim<-`(as.numeric(X), dim(X)), 
               list(NULL, paste0(rep(names(indf), each = 2), 1:2)))
}

其次,应用它:

Stringi(df)
#      A1 A2 B1 B2 C1 C2 D1 D2 E1 E2
# [1,]  1  1  0  1  1  1  1  1  1  1
# [2,]  1  1  1  1  1  1  1  1  1  1
# [3,]  0  1  0  1  0  1  0  1  0  1

在13000行乘200列中,cSplit对我来说只需不到11秒,而Stringi只需不到2.5秒。


显然,这已经考虑到未来版本的“splitstackshape”为this Gist of mine from last month shows :-)使用该版本的cSplit,时间从11秒减少到大约2.7秒