在R中生成随机排列

5
我尝试在 Sheldon M. Ross 的《Simulation (2006, 4ed., Elsevier)》中使用 R 实现一个例子,该例子希望生成一个随机排列,规定所有 n! 种可能的排序是等可能发生的,具体步骤如下:
- 首先随机选择数字 1,2,...,n 中的一个; - 将所选数字放置于位置 n; - 接着,在剩余的 n-1 个数字中随机选择一个,并将其放置于位置 n-1; - 然后,在剩余的 n-2 个数字中随机选择一个,并将其放置于位置 n-2; - 以此类推。
当然,我们也可以很容易地通过以下方法实现这一目标:
sample(1:n, replace=FALSE)

例如
> set.seed(0); sample(1:5, replace=FALSE)
[1] 1 4 3 5 2

然而,我想根据上述算法步骤手动获取类似的结果。接着我尝试:

## write the function
my_perm = function(n){ 
x = 1:n # initialize
k = n  #  position n
out = NULL
while(k>0){
  y = sample(x, size=1) # choose one of the numbers at random
  out = c(y,out) # put the number in position
  x = setdiff(x,out)  # the remaining numbers
  k = k-1 # and so on
}
out
}

## test the function
n = 5; set.seed(0); my_perm(n) # set.seed for reproducible

并拥有

[1] 2 2 4 5 1

这显然是不正确的,因为有两个 2。我该怎么解决这个问题?
2个回答

7
您已经正确实现了逻辑,但有一件需要注意的事情与R相关。
来自?sample 如果x的长度为1,在数字意义上是数值型(is.numeric),并且x>=1,则通过sample进行抽样,取样范围从1:x。
所以当最后一个数字在x中剩余,比如这个数字是4,抽样将从1:4进行,并返回其中的任何1个数字。
例如,
set.seed(0)
sample(4, 1)
#[1] 2

所以你需要调整你的函数,然后代码应该能够正常工作。

my_perm = function(n){ 
  x = 1:n # initialize
  k = n  #  position n
  out = NULL
  while(k>1){ #Stop the while loop when k = 1
    y = sample(x, size=1) # choose one of the numbers at random
    out = c(y,out) # put the number in position
    x = setdiff(x,out)  # the remaining numbers
    k = k-1 # and so on
  }
  out <- c(x, out) #Add the last number in the output vector.
  out
}

## test the function
n = 5
set.seed(0)
my_perm(n)
#[1] 3 2 4 5 1

一份出色而详细的答案!非常令人印象深刻! - John Stone

2

样本大小应大于1。您可以通过编写条件来打破它;

my_perm = function(n){ 
x = 1:n 
k = n  
out = NULL
while(k>0){
  if(length(x)>1){
     y = sample(x, size=1) 
  }else{
      y = x
  }
   
  out = c(y,out)
  x = setdiff(x,out)
  k = k-1 
}
out
}

n = 5; set.seed(0); my_perm(n)


[1] 3 2 4 5 1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接