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$ は要素が最も頻繁に発生する回数であり、ランダムな要素を選択できます (前の制約と一致します)。ただし、これらの数値が等しい場合、シーケンスの残りの部分では、最も頻度の高い値が 1 つおきの位置にある必要があります (その間の値はランダムに割り当てることができます)。この制約を認識すると、単一のパス スルーが許可されます (元のベクトルに要素が存在する以上のランダムな選択はありません)。

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 に答える