【问题标题】:Creating multiple pairs in R在 R 中创建多个对
【发布时间】:2013-03-22 14:50:31
【问题描述】:

我有一份人员名单:

people<-c("Betty", "Joe", "Bob", "Will", "Frank")

我想为每个人随机分配两个人(不允许自行分配),并且我希望每个人被分配给另一个人的次数相等(在上面的示例中,每个人只能被分配给再两次)。

所以例如比赛可能是

贝蒂(乔和鲍勃)、乔(鲍勃和威尔)、鲍勃(威尔和弗兰克)、威尔(弗兰克和贝蒂)

当然,我刚刚使用了他们的排序,但如果可以随机排序就好了。

任何想法从哪里开始?

【问题讨论】:

    标签: r match random-sample


    【解决方案1】:

    新的(更简单的)解决方案:使用来自 Ari B. Friedman 的 TaRifx 包中的 shift 函数

    tt <- sample(people)
    lapply(seq_len(length(tt))-1, function(x) shift(tt, x)[1:3])
    # if you don't want it to be ordered, just add a sample(.)
    lapply(seq_len(length(tt))-1, function(x) sample(shift(tt, x)[1:3]))
    # [[1]]
    # [1] "Bob"   "Frank" "Betty"
    # 
    # [[2]]
    # [1] "Frank" "Betty" "Joe"  
    # 
    # [[3]]
    # [1] "Betty" "Joe"   "Will" 
    # 
    # [[4]]
    # [1] "Joe"  "Will" "Bob" 
    # 
    # [[5]]
    # [1] "Will"  "Bob"   "Frank"
    

    旧的解决方案(对于这个想法): 我会走这条路。基本上,一旦你sample“人”,你可以总是去,1,2,3,2,3,4,3,4,5,4,5,1。所以,让我们这样做。也就是说,生成这些索引,然后对人员进行抽样并得到三元组。

    # generate index
    len <- length(people)
    choose <- 3 # at a time 
    idx <- outer(seq(choose), seq(choose+2)-1, '+')
    #      [,1] [,2] [,3] [,4] [,5]
    # [1,]    1    2    3    4    5
    # [2,]    2    3    4    5    6
    # [3,]    3    4    5    6    7
    
    # sample people
    tt <- sample(people)
    # [1] "Joe"   "Will"  "Bob"   "Frank" "Betty"
    max.idx <- 2*choose + 1
    tt[(len+1):max.idx] <- tt[seq(max.idx-len)]
    # [1] "Joe"   "Will"  "Bob"   "Frank" "Betty" "Joe"   "Will" 
    
    tt[idx]
    #  [1] "Joe"   "Will"  "Bob"   "Will"  "Bob"   "Frank" "Bob"   "Frank" "Betty" "Frank" 
    #  [15] "Betty" "Joe"  "Betty" "Joe"   "Will" 
    
    split(tt[idx], gl(ncol(idx), nrow(idx)))
    # $`1`
    # [1] "Joe"  "Will" "Bob" 
    # 
    # $`2`
    # [1] "Will"  "Bob"   "Frank"
    # 
    # $`3`
    # [1] "Bob"   "Frank" "Betty"
    # 
    # $`4`
    # [1] "Frank" "Betty" "Joe"  
    # 
    # $`5`
    # [1] "Betty" "Joe"   "Will" 
    

    现在我们可以把这一切都放在一个函数中:

    my_sampler <- function(x, choose) {
        len <- length(x)
        idx <- outer(seq(choose), seq(choose+2)-1, '+')
        sx  <- sample(x)
        max.idx <- 2*choose + 1
        sx[(len+1):max.idx] <- sx[seq(max.idx-len)]
        split(sx[idx], gl(ncol(idx), nrow(idx)))
    }
    # try it out
    my_sampler(people, 3)
    my_sampler(people, 4) # 4 at a time
    
    # if you want this and want a non-ordered solution, wrap this with `lapply` and `sample`
    
    lapply(my_sampler(people, 3), sample)
    

    【讨论】:

    • 但是名字的初始向量长度为​​5时只返回4个三元组?
    • OP 在他的输出中只有 4 个......所以我认为就是这样。将进行编辑。
    • 嗯,我明白你的意思了。我认为名单上的每个人都应该分配一些朋友,所以没有人会被排除在聚会之外! :-)
    • @Elizabeth 开头的sample 位会在您每次使用列表时重新排序?或者查看下面的我的解决方案,它也是 random
    • @Elizabeth,在这种情况下,例如,在“新解决方案”中,您可以将function(x) shift(tt, x)[1:3] 替换为function(x) sample(shift(tt, x)[1:3])。您只需创建您选择的 3 个不同的组合。这样就不会很明显了。
    【解决方案2】:

    有趣的问题。这会让你走到一半。缺少的一点是对人们处于相同数量的伙伴关系中的限制。如果您想随机将两个人分配给除他们自己以外的其他人,这可以像这样在一个班轮中实现......

    assigns <- lapply( people , function(x) { c( x , sample( people[!(people %in% x)] , 2 ) ) } )
    

    第一个人将被分配,最后两个将被分配。

    assigns
    #[[1]]
    #[1] "Betty" "Bob"   "Will" 
    
    #[[2]]
    #[1] "Joe"   "Bob"   "Frank"
    
    #[[3]]
    #[1] "Bob"   "Betty" "Joe"  
    
    #[[4]]
    #[1] "Will"  "Betty" "Joe"  
    
    #[[5]]
    #[1] "Frank" "Will"  "Betty"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-20
      • 2021-11-25
      • 1970-01-01
      • 1970-01-01
      • 2022-01-16
      • 2012-05-21
      • 2020-05-25
      • 2020-12-31
      相关资源
      最近更新 更多