扩展列表以包括组内所有可能的成对组合

时间:2017-11-14 01:52:44

标签: r dplyr

我目前正在进行随机化,其中对特定人群的个体进行抽样并将其放入定义大小的组中。结果是下面的数据框:

Ind Group
Sally   1
Bob 1
Sue 1
Joe 2
Jeff    2
Jess    2
Mary    2
Jim 3
James   3

是否有一个功能可以让我扩展数据集以显示组配对中的每一个可能性? (下面的期望输出)。配对不需要是互惠的。

Group   Ind1    Ind2
1   Sally   Bob
1   Sally   Sue
1   Sue Bob
2   Joe Jeff
2   Joe Jess
2   Joe Mary
2   Jeff    Jess
2   Jess    Mary
2   Jeff    Mary
3   Jim James

我觉得必须有一种方法可以在dplyr中做到这一点,但对于我的生活,我似乎无法解决它。

3 个答案:

答案 0 :(得分:3)

替代dplyr& tidyr方法:管道有点长,但对我来说,争吵感觉更直接。首先将每个组中的所有记录组合在一起。接下来,将所有名称汇总并按字母顺序排列,以便能够消除倒数/重复。然后最后将结果再分开。

left_join(dt, dt, by = "Group") %>% 
    filter(Ind.x != Ind.y) %>% 
    rowwise %>%
    mutate(name = toString(sort(c(Ind.x,Ind.y)))) %>% 
    select(Group, name) %>% 
    distinct %>% 
    separate(name, into = c("Ind1", "Ind2")) %>% 
    arrange(Group, Ind1, Ind2)
  • 从每组中所有记录的弱交叉连接开始
  • filter自我加入
  • 收集每行中的所有名称,对其进行排序,并在名称列中将它们放在一起。
  • 现在名称按字母顺序排列,删除按字母顺序排列的倒数
  • 将数据拆分回单独的列。
# A tibble: 10 x 3
   Group  Ind1  Ind2
 * <int> <chr> <chr>
 1     1   Bob Sally
 2     1 Sally   Sue
 3     1   Bob   Sue
 4     2  Jeff   Joe
 5     2  Jess   Joe
 6     2   Joe  Mary
 7     2  Jeff  Jess
 8     2  Jeff  Mary
 9     2  Jess  Mary
10     3 James   Jim

答案 1 :(得分:2)

以下是使用data.table的选项。转换为data.tablesetDT(dt)),按“组”分组进行交叉加入(CJ)并删除duplicated元素

library(data.table)
setDT(dt)[, CJ(Ind1 = Ind, Ind2 = Ind, unique = TRUE)[Ind1 != Ind2], 
             Group][!duplicated(data.table(pmax(Ind1, Ind2), pmin(Ind1, Ind2)))]
#   Group  Ind1  Ind2
#1:     1   Bob Sally
#2:     1   Bob   Sue
#3:     1 Sally   Sue
#4:     2  Jeff  Jess
#5:     2  Jeff   Joe
#6:     2  Jeff  Mary
#7:     2  Jess   Joe
#8:     2  Jess  Mary
#9:     2   Joe  Mary
#10:    3 James   Jim

或使用combn按'组'

setDT(dt)[, {temp <- combn(Ind, 2); .(Ind1 = temp[1,], Ind2 = temp[2,])}, Group]

答案 2 :(得分:1)

使用dplyr的解决方案。我们可以使用group_bydocombn函数应用于每个组,并将结果组合在一起形成数据框。

library(dplyr)
dt2 <- dt %>%
  group_by(Group) %>%
  do(as_data_frame(t(combn(.$Ind, m = 2)))) %>%
  ungroup() %>%
  setNames(sub("V", "Ind", colnames(.)))
dt2

# # A tibble: 10 x 3
#    Group  Ind1  Ind2
#    <int> <chr> <chr>
#  1     1 Sally   Bob
#  2     1 Sally   Sue
#  3     1   Bob   Sue
#  4     2   Joe  Jeff
#  5     2   Joe  Jess
#  6     2   Joe  Mary
#  7     2  Jeff  Jess
#  8     2  Jeff  Mary
#  9     2  Jess  Mary
# 10     3   Jim James

数据

dt <- read.table(text = "Ind Group
Sally   1
Bob 1
Sue 1
Joe 2
Jeff    2
Jess    2
Mary    2
Jim 3
James   3",
                 header = TRUE, stringsAsFactors = FALSE)