Генерация случайных пар предметов в векторе - PullRequest
0 голосов
/ 05 июля 2018

Предположим, у меня есть символьный вектор (например, myv = c('a', 'b', 'c', 'd', 'e')), я хотел бы случайным образом генерировать n = length(myv) пары partner1 - partner2 из этого вектора, зная, что:

  • все предметы должны быть 1 раз partner1 и 1 раз partner2, не больше и не меньше, в случайном порядке;
  • элемент не может быть партнером с самим собой (сохранение значения для partner1 и partner2 не работает).

Я не нахожу элегантного способа сделать это (например, с помощью sample, combn или expand.grid), поэтому в настоящее время я использую уродливый цикл for:

set.seed(11)

myv = letters[1:5]

irand = sample(length(myv), length(myv)) # to randomly select partner1

allpairs = expand.grid(myv, myv)
# remove pairs of the same item
allpairs = allpairs[allpairs[,1]!=allpairs[,2],]

usedpartner2 = c() # to store the partner2 which are already used
mypairs = c() # to store results
for (i in 1:length(myv)) {
  partner1 = myv[irand[i]]
  # the potential partner2 must be different from partner1 and not already used
  candidates = allpairs[allpairs[, 1]==partner1 & !(allpairs[, 2] %in% usedpartner2), 2]
  partner2 = as.character(candidates[sample(length(candidates), 1)])
  usedpartner2 = c(usedpartner2, partner2)
  mypairs = rbind(mypairs, c(partner1, partner2))
}

mypairs
#      [,1] [,2]
# [1,] "b"  "e" 
# [2,] "a"  "b" 
# [3,] "e"  "a" 
# [4,] "d"  "c" 
# [5,] "c"  "d" 

1 Ответ

0 голосов
/ 05 июля 2018

Вы можете увидеть myv как кольцо и повернуть его случайным образом, добавив что-то в molulo (%%) из length(myv) (ноль исключен). (length(myv) - 1) %% length(myv) следует исключить, чтобы избежать сопряжения элементов. Это должно работать с произвольной длиной myv и семян соответственно.

matrix(c(myv, 
         myv[(seq_along(myv) + sample(seq_along(myv)[- (length(myv) - 1)], 1)) 
             %% length(myv) + 1]), 
       ncol=2)

Затем вы легко можете превратить это в функцию.

pairOff <- function(x) {
  x <- sample(x)  # to get first column into random order, too
  M <- matrix(c(x, 
                x[(seq_along(x) + sample(seq_along(x)[- (length(x) - 1)], 1)) 
                  %% length(x) + 1]), 
              ncol=2)
  return(M)
}

Уступая

> pairOff(myv)
     [,1] [,2]
[1,] "d"  "e" 
[2,] "c"  "a" 
[3,] "b"  "d" 
[4,] "e"  "c" 
[5,] "a"  "b" 

Данные

set.seed(165472)
myv <- letters[1:5]
...