8

我对 R 很陌生,但是我进行了很多搜索,但没有找到我的问题的答案。

我有一个多次重复 8 位数字的向量:

allNum <- c(rep(1, 70), rep(2, 70), rep(3, 35), rep(4, 35), 
            rep(5, 70), rep(6, 70), rep(7, 35), rep(8, 35))

现在我想对此进行排列(大概使用sample(allNum, 420, replace=FALSE)),但我不想要任何连续的相同数字 - 例如:1 2 2 8

有没有一种简单的方法可以做到这一点?

4

3 回答 3

3

您有一个问题,即有可能随机选择元素而不是受限于您的选择。特别是,如果您必须选择的元素数量超过 $2n-1$,其中 $n$ 是最频繁出现的元素的次数,您可以选择一个随机元素(与前面的约束一致)。但是,如果这些数字相等,那么对于序列的其余部分,最频繁的值必须位于每隔一个位置(并且可以随机分配之间的值)。识别此约束允许单次通过(随机选择不超过原始向量中的元素)。

permute.nonconsec <- function(allNum) {
  fully.constrained <- function(x) {
    2*max(table(x)) - 1 == length(x)
  }
  permuted <- numeric(length(allNum))
  permuted[1] <- sample(allNum, 1)
  allNum <- allNum[-min(which(allNum==permuted[1]))]
  for (i in seq_along(allNum)+1) {
    if(fully.constrained(allNum)) {
      # switch to deterministic algorithm
      # determine which value is the constraining one
      r <- rle(sort(allNum))
      limiter <- r$values[r$lengths==max(r$lengths)]
      permuted[seq(i, length(permuted), by=2)] <- limiter
      remaining <- allNum[allNum != limiter]
      if (length(remaining)>0) {
        permuted[seq(i+1, length(permuted), by=2)] <- 
          remaining[sample.int(length(remaining))]
      }
      break;
    }
    available <- allNum[allNum != permuted[i-1]]
    permuted[i] <- available[sample.int(length(available), 1)]
    allNum <- allNum[-min(which(allNum==permuted[i]))]
  }
  permuted
}

如果没有可能的安排:这将失败length(x) < 2 * max(table(x)) - 1,但如果需要,可以添加初始检查。

于 2013-04-04T19:32:21.597 回答
0

这是一个简单的算法:

N = 420
i = as.integer(runif(1, 1, length(allNum)))
result = allNum[i]
allNum = allNum[-i]
while (N != 1) {
  N = N - 1

  # pick a random value that's different from last chosen one
  last = result[length(result)]
  i = as.integer(runif(1, 1, sum(allNum != last)))
  result = c(result, allNum[allNum != last][i])

  # remove any (doesn't matter which) element of allNum that's
  # equal to last choice, to sample without replacement
  last = result[length(result)]
  allNum = allNum[-which(allNum == last)[1]]
}
于 2013-04-04T22:48:59.450 回答
0

借用先前的答案,一种方法是蛮力并继续采样,直到获得具有所需特征的排列。

nonconsec.permute <- function(pop,size) {
  while(!exists("x",inherits=FALSE) || 0 %in% diff(x)) {
    x <- sample(pop, size, replace=F)
  }
}

但是,以下命令需要很长时间,因为在您提供的示例中,相同的连续数字非常常见。所以这种方法在你的具体情况下是不可行的。

nonconsec.permute(allNum,420)
于 2013-04-04T18:28:48.820 回答