R样本概率:默认值相等;为什么指定相等权重会导致返回不同的值?

时间:2014-04-26 21:30:20

标签: r probability sample

我对R中的样本函数有一个简单的问题。我从0和1中随机抽样并将它们加在一起,从长度为5的输入向量求和,它指定要运行的试验次数并将种子设置为生成可重现的随机数。种子按预期工作,但我根据我在prob语句中的内容得到不同的随机数矩阵。在这种情况下,我假设prob = NULL应该与prob = c(0.5,0.5)相同。为什么不呢?

vn<-c(12, 44, 9, 17, 28)

> do.call(cbind, lapply(c(1:10),function(X) {set.seed(X); sapply(vn, function(Y) sum(sample(x=c(0,1),size=Y,replace=T)), simplify=TRUE)}))

     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]    6    7    7    6    6    9    3    6    2     5
[2,]   22   21   20   29   22   24   24   19   25    19
[3,]    4    8    3    5    4    4    4    6    4     2
[4,]    8    4   12    9   11    7    9   10    8     8
[5,]   13    9   11   14   12   14   10   13   11    12

> do.call(cbind, lapply(c(1:10),function(X) {set.seed(X); sapply(vn, function(Y) sum(sample(x=c(0,1),size=Y,replace=T, prob=c(0.5,0.5))), simplify=TRUE)}))

     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]    6    5    5    6    6    3    9    6   10     7
[2,]   22   23   24   15   22   20   20   25   19    25
[3,]    5    1    6    4    5    5    5    3    5     7
[4,]    9   13    5    8    6   10    8    7    9     9
[5,]   15   19   17   14   16   14   18   15   17    16

更新:

我使用输入向量

将采样扩展到100
vn<-seq(0,100,5)

并将没有概率(test1)和prob = c(0.5,0.5)的输出矩阵的rowMeans与预期平均值进行比较。有趣的是,test1和test2通过反转符号完全相同。这是为什么?谢谢!

> rowMeans(test1)-seq(0,100,5)/2
 [1]  0.00 -0.07 -0.01 -0.35 -0.07  0.19 -0.07  0.24  0.21  0.46  0.20  0.50 -0.37 -0.35  0.00  0.64 -0.59  0.63 -1.19  0.44 -0.38

> rowMeans(test2)-seq(0,100,5)/2
 [1]  0.00  0.07  0.01  0.35  0.07 -0.19  0.07 -0.24 -0.21 -0.46 -0.20 -0.50  0.37  0.35  0.00 -0.64  0.59 -0.63  1.19 -0.44  0.38

2 个答案:

答案 0 :(得分:4)

我将评论更新为答案。 sample使用不同的c例程进行统一采样和加权采样。虽然你使用的是相同的权重,但无论如何R都会调用加权采样。 要看到这一点,请考虑

> set.seed(1)
> sample.int(100)
  [1]  27  37  57  89  20  86  97  62  58   6  19  16  61  34  67  43  88  83
 [19]  32  63  75  17  51  10  21  29   1  28  81  25  87  42  70  13  55  44
 [37]  78   7  45  26  50  39  46  82  30  65   2  84  59  36  24  85  22  12
 [55]   4   5  14  23  73  79  99  47  18  95  60  77  41  53   3  69  11  71
 [73]  35  31  40  49  76   9  38  64  80  66   8  91  33  92 100  54  98  94
 [91]  52  74  68  72  93  15  56  48  90  96
> set.seed(1)
> sample.int(100, prob = rep(1/100, 100))
  [1]  28  39  60  93  21  91  96  67  63   7  22  18  71  41  79  51  74   1
 [19]  38  78  94  20  64  12  29  40   2  42  87  35  50  61  52  17  84  69
 [37]  81  10  73  44  85  65  80  54  49  82   4  46  75  68  43  90  36  23
 [55]   8  11  30  55  66  34  97  26  47  31  70  24  53  86   6  95  32  89
 [73]  27  33  56  98  88  25  77 100  37  62  19  15  76  13  59   5  14   9
 [91]  45   3  83  99  72  58  48  57  92  16

请注意两个不同的采样序列。

答案 1 :(得分:3)

正如Randy所建议的那样,sample.int使用了不同的例程,具体取决于prop是否为NULL。

在您的情况下,它会返回反向结果:

> set.seed(1); sample(c(0,1), size=20, replace=TRUE)
 [1] 0 0 1 1 0 1 1 1 1 0 0 0 1 0 1 0 1 1 0 1
> set.seed(1); sample(c(0,1), size=20, replace=TRUE, prob=c(.5,.5))
 [1] 1 1 0 0 1 0 0 0 0 1 1 1 0 1 0 1 0 0 1 0

发生了什么?

对于前者,我们点击src/main/random.c:546行:

 for (int i = 0; i < k; i++) iy[i] = (int)(dn * unif_rand() + 1);

这个很简单。 unif_rand()返回介于0和1之间的值(并且永远不会返回1),dn为2(x中的元素数量),因此iy[i]设置为{{ 1}}或1,具体取决于2是否分别返回值unif_rand()< .5;这是从>= .5中选择的值。

后者有点复杂。由于指定了xprob会在do_sample调用函数ProbSampleReplace。在这里,概率按照降序排序,函数src/main/random.c:309位于revsort。这对概率使用堆排序,并且使用具有相等概率的双元素向量,它会反转顺序。

src/main/sort.c:248再次调用ProbSampleReplace,但这一次将其映射到翻转向量顺序后计算的累积概率,因此如果unif_rand()返回值unif_rand(),返回第二个值(在您的示例中为< 0.5)。这是将1映射到unif_rand()

中的值的代码
x

因此,在两个元素的概率相等的情况下,将概率明确设置为/* compute the sample */ for (i = 0; i < nans; i++) { rU = unif_rand(); for (j = 0; j < nm1; j++) { if (rU <= p[j]) break; } ans[i] = perm[j]; } 将返回相同调用的反转而不设置概率。有两个以上的元素,它不会总是反转它们,但它不会返回相同的顺序。

这也解释了为什么费尔南多的建议有效。这些值足够接近.5,以便不更改此示例的结果,并且堆排序以原始顺序返回值。

此表达式返回与第一行代码相同的矩阵:

c(0.5, 0.5)

此处,do.call(cbind, lapply(c(1:10),function(X) {set.seed(X); sapply(vn, function(Y) sum(sample(x=c(1,0),size=Y,replace=T, prob=c(0.5,0.5))), simplify=TRUE)})) 中条目的顺序已被反转,以考虑两个元素的相等值排序(交换条目)。

当然这都是学术性的。在实践中,置换等概率条目的顺序并不重要。

上面的源文件和行号参考x