我希望将每列中用逗号分隔的值对分成新数据框中的两个相邻列,并为两个新列中的每一列分配相同的列名。
也就是说,我想转换它:
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行,所以我需要一种自动分割列的方法,并为数据框的第二个版本指定名称。
答案 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秒