在 R 中生成随机排列

Joh*_*one 5 algorithm r permutation

我尝试使用Simulation (2006, 4ed., Elsevier)Sheldon M. Ross 的 R 实现一个示例,它想要生成随机排列,内容如下:

  • 假设我们有兴趣生成数字 1,2,... ,n 的排列

  • 这就是所有 n! 可能的排序是同样可能的。

  • 以下算法将通过以下方式完成此任务

    • 首先随机选择数字 1,2,...,n 之一;
    • 然后将该数字放入位置 n;
    • 然后它随机选择剩余的 n-1 个数字之一并将该数字放在位置 n-1 ;
    • 然后它随机选择剩余的 n-2 个数字之一并将其放在位置 n-2 ;
    • 等等

当然,我们可以通过以下方式轻松实现数字 1,2,...,n 的随机排列

sample(1:n, replace=FALSE)
Run Code Online (Sandbox Code Playgroud)

例如

> set.seed(0); sample(1:5, replace=FALSE)
[1] 1 4 3 5 2
Run Code Online (Sandbox Code Playgroud)

但是,我想根据上述算法步骤手动得到类似的结果。然后我尝试

## 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
Run Code Online (Sandbox Code Playgroud)

并有

[1] 2 2 4 5 1
Run Code Online (Sandbox Code Playgroud)

这显然是不正确的,因为有两个2. 我该如何解决这个问题?

Ron*_*hah 7

您已经正确实现了逻辑,但您只需要注意与 相关的一件事R

?sample

如果 x 的长度为 1,是数字(在 is.numeric 的意义上)并且 x >= 1,则通过样本进行采样从 1:x 开始

因此,当 中剩余最后一个数字时x,假设该数字为 4,将从 1:4 开始采样,并返回其中的任何 1 数字。

例如,

set.seed(0)
sample(4, 1)
#[1] 2
Run Code Online (Sandbox Code Playgroud)

因此,您需要调整您的功能,然后代码才能正常工作。

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
Run Code Online (Sandbox Code Playgroud)


Sam*_*kel 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
Run Code Online (Sandbox Code Playgroud)