R:将多个列合并为同一行中的列单元格对
我希望将数据帧中的多个列合并/配对为同一行中的列单元格对。例如,R:将多个列合并为同一行中的列单元格对,r,dataframe,reshape,R,Dataframe,Reshape,我希望将数据帧中的多个列合并/配对为同一行中的列单元格对。例如,df1应转换为df2 df1 col1 col2 col3 1 2 3 0 0 1 df2 c1 c2 1 2 1 3 2 3 0 0 0 1 0 1 该解决方案应可扩展为df1s(方式)超过三列 我考虑过熔化/重塑/dcast,但还没有找到解决方案。数据帧中没有NAs。谢谢大家! 编辑:重塑刚刚产生了错误,所以我考虑 combn(df1[1,2] comb2您
df1
应转换为df2
df1
col1 col2 col3
1 2 3
0 0 1
df2
c1 c2
1 2
1 3
2 3
0 0
0 1
0 1
该解决方案应可扩展为df1
s(方式)超过三列
我考虑过熔化/重塑/dcast,但还没有找到解决方案。数据帧中没有NAs。谢谢大家!
编辑:重塑
刚刚产生了错误,所以我考虑
combn(df1[1,2]
comb2您的编辑与我下面的答案非常相似,您只需要在df1的行上每次迭代都返回结果。使用data.table是加速rbind的好方法
编辑:不幸的是,当我切换到data.table方法时,结果发现rbindlist()导致了答案错误(如下面的评论所指出的)。因此,尽管可能会稍微慢一点,但我认为预分配数据帧和使用rbind可能是最好的选择
EDIT2:将预先分配的df切换到更一般的行数
df1 = as.data.frame(matrix(c(1,2,3,4,0,0,1,1), byrow = TRUE, nrow = 2))
nrow_combn = nrow(t(combn(df1[1,], m = 2)))
nrow_df = nrow(df1) * nrow_combn
df2 = data.frame(V1 = rep(0, nrow_df), V2 = rep(0, nrow_df))
for(i in 1:nrow(df1)){
df2[(((i-1)*nrow_combn)+1):(i*(nrow_combn)), ] = data.frame(t(combn(df1[i,], m = 2)))
}
以下是我将采取的方法
创建一个函数,该函数使用来自“data.table”的rbindlist
和来自base R的combn
。该函数如下所示:
lengthener <- function(indf) {
temp <- rbindlist(
combn(names(indf), 2, FUN = function(x) indf[x], simplify = FALSE),
use.names = FALSE, idcol = TRUE)
setorder(temp[, .id := sequence(.N), by = .id], .id)[, .id := NULL][]
}
在一些较大的数据上也进行测试:
set.seed(1)
M <- as.data.frame(matrix(sample(100, 100*100, TRUE), 100))
system.time(out <- lengthener(M))
# user system elapsed
# 0.19 0.00 0.19
out
# V1 V2
# 1: 27 66
# 2: 27 27
# 3: 27 68
# 4: 27 66
# 5: 27 56
# ---
# 494996: 33 13
# 494997: 33 66
# 494998: 80 13
# 494999: 80 66
# 495000: 13 66
set.seed(1)
我对R不熟悉,因此不是很有文化,但我已经尝试重新塑造,将其转换为长格式。但是,我找不到一种方法在一点上只对两列。请在问题中包含您尝试的代码。谢谢-我已经包含了它。重塑刚刚产生的错误
——但这不是代码。难道你不想理解为什么你所尝试的会产生错误吗?谢谢你的努力!我尝试过你的方法,但结果不是你想要的:它产生2行6列,只是复制每个单元格的元素。我不知道为什么,因为基本的t(combn(…
解决方案产生了正确的结果,但一次只能生成一行。无论用户使用哪种工具,对象的增长速度都可能很慢。@RomanLuštrik您读过我发布的链接吗?在那个模拟中,这种方法比预分配数据帧更快。感谢您的编辑,@AndyMcKenzie!它适用于此示例,但事实并非如此可缩放nrow_df=ncol(df1)*nrow(df1)的b/c
。例如,在初始样本中有四列将产生4个choose 2=6个组合,每行总共12个,而代码只创建了8个。编辑:修复可能是nrow\u df5谢谢,@Ananda Mahto!我已经成功地处理了上面的另一个答案,但感谢您的努力!@user5835099,没问题。只是仅供参考,我已经在中添加了这一点。lengther()
函数还允许您为combn
指定“n”。我的答案主要是为了说明如果需要,如何实现更高的效率,因为Andy无法使代码与“data.table”一起工作。
set.seed(1)
M <- as.data.frame(matrix(sample(100, 100*100, TRUE), 100))
system.time(out <- lengthener(M))
# user system elapsed
# 0.19 0.00 0.19
out
# V1 V2
# 1: 27 66
# 2: 27 27
# 3: 27 68
# 4: 27 66
# 5: 27 56
# ---
# 494996: 33 13
# 494997: 33 66
# 494998: 80 13
# 494999: 80 66
# 495000: 13 66
funAMK <- function(indf) {
nrow_combn = nrow(t(combn(indf[1,], m = 2)))
nrow_df = nrow(indf) * nrow_combn
df2 = data.frame(V1 = rep(0, nrow_df), V2 = rep(0, nrow_df))
for(i in 1:nrow(indf)){
df2[(((i-1)*nrow_combn)+1):(i*(nrow_combn)), ] = data.frame(t(combn(indf[i,], m = 2)))
}
df2
}
> system.time(funAMK(M))
user system elapsed
16.03 0.16 16.37