我有一个带有一个id列(下面是x)的data.frame,以及一些变量(下面的y1,y2)。
x y1 y2
1 1 43 55
2 2 51 53
[...]
我想从中生成的是一个数据框,其中前两列涵盖x的每个有序组合(除非它们相等)以及与订单相关的每个变量的列。数据框头和前两行看起来像这样(手动完成,请原谅错误):
xi xj y1i y1j y2i y2j
1 2 43 51 55 53
2 1 51 43 53 55
[...]
因此,每一行都将容纳一个源和目的地(i和j),然后在每个源和目的地为y1加值。
我正在慢慢学习R数据操作,但是这个让我很难受。对于这一行的赞誉可以解决这个问题,以及更具可读性的教学答案。
答案 0 :(得分:4)
这可行(除了订单之外)
firstdf <- data.frame(x = c( 1, 2, 4, 5),
y1 = c(43,51,57,49), y2 = c(55,53,47,44))
co <- combn(firstdf$x,2)
seconddf <- data.frame(xi = c(co[1,], co[2,]), xj = c(co[2,], co[1,]))
thirddf <- merge(merge(seconddf, firstdf, by.x = "xj", by.y = "x" ),
firstdf, by.x = "xi", by.y = "x", suffixes = c("j", "i") )
生产
> thirddf
xi xj y1j y2j y1i y2i
1 1 2 51 53 43 55
2 1 5 49 44 43 55
3 1 4 57 47 43 55
4 2 4 57 47 51 53
5 2 1 43 55 51 53
6 2 5 49 44 51 53
7 4 5 49 44 57 47
8 4 1 43 55 57 47
9 4 2 51 53 57 47
10 5 1 43 55 49 44
11 5 2 51 53 49 44
12 5 4 57 47 49 44
第一行和第五行与您的示例匹配。
如果您按照给定的firstdf
并坚持一行,那么您可以将其转换为
merge(merge(data.frame(xi = c(combn(firstdf$x,2)[1,], combn(firstdf$x,2)[2,]), xj = c(combn(firstdf$x,2)[2,], combn(firstdf$x,2)[1,])), firstdf, by.x = "xj", by.y = "x" ), firstdf, by.x = "xi", by.y = "x", suffixes = c("j", "i") )
但我真的没有看到这一点
答案 1 :(得分:4)
两条线是我能做的最好的线路并且仍然保持合情合理:( 编辑:请参阅单线的答案底部。)
创建一些数据:
n <- 4
a <- cbind(x=LETTERS[1:n], y=letters[1:n])
a
x y
[1,] "A" "a"
[2,] "B" "b"
[3,] "C" "c"
[4,] "D" "d"
代码:
f <- function(x, i){cbind(i, x[i[,1],], x[i[,2],])}
f(a, t(combn(seq_len(nrow(a)), 2)))
结果:
x y x y
[1,] "1" "2" "A" "a" "B" "b"
[2,] "1" "3" "A" "a" "C" "c"
[3,] "1" "4" "A" "a" "D" "d"
[4,] "2" "3" "B" "b" "C" "c"
[5,] "2" "4" "B" "b" "D" "d"
[6,] "3" "4" "C" "c" "D" "d"
修改强>
这可以通过使用匿名函数变成单行:
(function(x, i=t(combn(seq_len(nrow(a)), 2))){cbind(i, x[i[,1],], x[i[,2],])})(a)
x y x y
[1,] "1" "2" "A" "a" "B" "b"
[2,] "1" "3" "A" "a" "C" "c"
[3,] "1" "4" "A" "a" "D" "d"
[4,] "2" "3" "B" "b" "C" "c"
[5,] "2" "4" "B" "b" "D" "d"
[6,] "3" "4" "C" "c" "D" "d"
答案 2 :(得分:2)
我不确定你到底想要什么,但据我的理解,这可能接近你想要的:
> library(combinat) # for permn
> library(plyr) # for llply
>
> # sample data
> d <- data.frame(x = 1:3, y1 = rnorm(3), y2 = rnorm(3))
> d
x y1 y2
1 1 -0.17525893 -1.1660321
2 2 -0.05585689 -0.2059244
3 3 0.90500983 -1.3067601
>
> # permutation of rows
> idx <- permn(nrow(d))
> idx
[[1]]
[1] 1 2 3
... snip ...
[[6]]
[1] 2 1 3
>
> # a list of perm-ed data.frame
> d2 <- llply(idx, function(i)data.frame(idx = 1:nrow(d), d[i,]))
> d2
[[1]]
idx x y1 y2
1 1 1 -0.17525893 -1.1660321
2 2 2 -0.05585689 -0.2059244
3 3 3 0.90500983 -1.3067601
... snip ...
[[6]]
idx x y1 y2
2 1 2 -0.05585689 -0.2059244
1 2 1 -0.17525893 -1.1660321
3 3 3 0.90500983 -1.3067601
>
> # merge htam
> d3 <- subset(Reduce(function(df1, df2) merge(df1, df2, by="idx"), d2), select = -c(idx))
> d3
x.x y1.x y2.x x.y y1.y y2.y x.x.1 y1.x.1 y2.x.1 x.y.1 y1.y.1 y2.y.1 x.x.2 y1.x.2 y2.x.2 x.y.2
1 1 -0.17525893 -1.1660321 1 -0.17525893 -1.1660321 3 0.90500983 -1.3067601 3 0.90500983 -1.3067601 2 -0.05585689 -0.2059244 2
2 2 -0.05585689 -0.2059244 3 0.90500983 -1.3067601 1 -0.17525893 -1.1660321 2 -0.05585689 -0.2059244 3 0.90500983 -1.3067601 1
3 3 0.90500983 -1.3067601 2 -0.05585689 -0.2059244 2 -0.05585689 -0.2059244 1 -0.17525893 -1.1660321 1 -0.17525893 -1.1660321 3
y1.y.2 y2.y.2
1 -0.05585689 -0.2059244
2 -0.17525893 -1.1660321
3 0.90500983 -1.3067601
>
> # and here is the one-liner version
> subset(Reduce(function(df1, df2) merge(df1, df2, by="idx"), llply(permn(nrow(d)), function(i)data.frame(idx=1:nrow(d), d[i,]))), select=-c(idx))
x.x y1.x y2.x x.y y1.y y2.y x.x.1 y1.x.1 y2.x.1 x.y.1 y1.y.1 y2.y.1 x.x.2 y1.x.2 y2.x.2 x.y.2
1 1 -0.17525893 -1.1660321 1 -0.17525893 -1.1660321 3 0.90500983 -1.3067601 3 0.90500983 -1.3067601 2 -0.05585689 -0.2059244 2
2 2 -0.05585689 -0.2059244 3 0.90500983 -1.3067601 1 -0.17525893 -1.1660321 2 -0.05585689 -0.2059244 3 0.90500983 -1.3067601 1
3 3 0.90500983 -1.3067601 2 -0.05585689 -0.2059244 2 -0.05585689 -0.2059244 1 -0.17525893 -1.1660321 1 -0.17525893 -1.1660321 3
y1.y.2 y2.y.2
1 -0.05585689 -0.2059244
2 -0.17525893 -1.1660321
3 0.90500983 -1.3067601
如果您提供更详细的信息,可能会得到更好的答案。
答案 3 :(得分:1)
嗯,它没有接近一个单线程(我有点怀疑是可能的),但这是一个'天真'的方法:
dat <- data.frame(x=1:5,y1=6:10,y2=11:15)
#Collect all ordered pairs of elements of x
tmp <- expand.grid(dat$x,dat$x)
tmp <- tmp[tmp[,1] != tmp[,2],]
#Init a matrix to hold the results
rs <- as.matrix(cbind(tmp,matrix(NA,nrow(tmp),4)))
#Loop through each ordered pair
for (i in 1:nrow(rs)){
rs[i,3:6] <- c(dat$y1[rs[i,1:2]],dat$y2[rs[i,1:2]])
}
我没有列出这些列,但事后很容易做到。
不是很优雅,但可能会让你开始......