在组内创建所有对并维护变量

时间:2016-02-16 20:21:27

标签: r

我有一个大约有30k观测值的数据帧,分为300组。例如

id, group, x, y
1,  1,     2, 3
2,  1,     4, 3
3,  1,     2, 4
4,  2,     5, 4
5,  2,     5, 3
6,  2,     6, 4

我想这样做

pair, group, x_i, x_j, y_i, y_j
12,   1,     2,   4,   3,   3
13,   1,     2,   2,   3,   4
23,   1,     4,   2,   3,   4
45,   2,     5,   5,   4,   3

等等。我找到了一些主题,但它们似乎并不完全适用于我的问题。

2 个答案:

答案 0 :(得分:2)

combn函数可用于生成每对相应的xy值。我们使用grouplapply运营。 lapply返回一个列表,因此我们使用rbind将每个列表元素(每个group的结果)放回一个数据框中。

new.dat = lapply(unique(dat$group), function(g) {
  data.frame(pairs = apply(t(combn(dat$id[dat$group==g], 2)), 1, paste, collapse=""),
             group=g,
             x = t(combn(dat$x[dat$group==g], 2)),
             y = t(combn(dat$y[dat$group==g], 2)))
})

do.call(rbind, new.dat)
  pairs group x.1 x.2 y.1 y.2
1    12     1   2   4   3   3
2    13     1   2   2   3   4
3    23     1   4   2   3   4
4    45     2   5   5   4   3
5    46     2   5   6   4   4
6    56     2   5   6   3   4

你也可以使用split,这可以节省一些打字,但在我的机器上慢了约10%:

lapply(split(dat, dat$group), function(df) {
  data.frame(pairs = apply(t(combn(df$id, 2)), 1, paste, collapse=""),
             group=g,
             x = t(combn(df$x, 2)),
             y = t(combn(df$y, 2)))
})

答案 1 :(得分:0)

我不会说这是一个不理想的结果,但它应该有效:

df <- read.table(text="id, group, x, y
1,1,2,3
2,1,4,3
3,1,2,4
4,2,5,4
5,2,5,3
6,2,6,4", header=T, sep=",")

df.new <- do.call(rbind,lapply(tapply(df$id, df$group, combn, m=2), FUN=function(x) data.frame(pairi=x[1,], pairj=x[2,])))
df.new <- do.call(rbind,apply(df.new, 1, FUN=function(x) data.frame(pair=paste0(x[1], x[2]),group=df[df$id==x[1], 'group'], x_i=df[df$id==x[1],'x'], x_j=df[df$id==x[2],'x'], y_i=df[df$id==x[1],'y'], y_j=df[df$id==x[2],'y'] )))
df.new
    pair group x_i x_j y_i y_j
1.1   12     1   2   4   3   3
1.2   13     1   2   2   3   4
1.3   23     1   4   2   3   4
2.1   45     2   5   5   4   3
2.2   46     2   5   6   4   4
2.3   56     2   5   6   3   4