我有两列中的数据,如下所示
Id Value
1 a
2 f
1 c
1 h
2 a
我希望根据相同的ID(例如
)将所有可能组合中的“值”列的数据结合起来(a,c)
(a,h)
(c,h)
(f,a)
是否有任何R或Python或VBA代码来完成此任务?
答案 0 :(得分:2)
使用R
您可以尝试:
library(purrr)
df %>%
split(.$Id) %>%
map(~ t(combn(.$Value, 2)))
给出了:
#$`1`
# [,1] [,2]
#[1,] "a" "c"
#[2,] "a" "h"
#[3,] "c" "h"
#
#$`2`
# [,1] [,2]
#[1,] f a
#Levels: a c f h
答案 1 :(得分:2)
要使用基数R返回包含这些组合的字符矩阵,请尝试
do.call(rbind, t(sapply(split(df, df$Id), function(i) t(combn(i$Value, 2)))))
[,1] [,2]
[1,] "a" "c"
[2,] "a" "h"
[3,] "c" "h"
[4,] "f" "a"
每一行都是理想的组合。
为了稍微打破这一点,split
将data.frame由Id拆分为两个data.frames的列表。然后sapply
被提供此列表和combn
函数以查找这些data.frames中的成对组合。每个data.frame(这是一个矩阵)的结果将使用t
转换为适合您所需的结构。最后,这个矩阵列表被输入do.call
,使用rbind
返回最终矩阵。
注意:假设值列是字符(不是讨厌的因子变量类型)。通过在读取函数中添加as.is = TRUE参数(或更长的stringsAsFactors = FALSE),可以在read.
函数族中轻松完成此操作,如read.csv
和read.table
。如果变量已经是一个因素,您可以将i$Value
语句包装在as.character
:as.character(i$Value)
的末尾附近,它将根据需要运行。
答案 2 :(得分:2)
另一种方式(可能稍快一点,因为它利用了您正在寻找所有对的事实,并避免combn
和t
):
require(data.table)
dt[, .( c1 = rep(Value, (.N:1)-1L), c2 = rep(Value, (1:.N)-1L) ), by=Id]
# Id c1 c2
# 1: 1 a c
# 2: 1 a h
# 3: 1 c h
# 4: 2 f a
.N
包含每个组的观察次数。
其中dt是:
dt = fread('Id Value
1 a
2 f
1 c
1 h
2 a')