从1号到20号生成10万个3号样本,无需更换

时间:2016-05-24 06:36:47

标签: r sampling

我正在尝试从数字1到20生成大约3个大小为3的样本,而不进行替换,并在R中使用以下代码:

s <- sample(N,3,pi<-n*x/sum(x),replace=FALSE)
[1] 12  6 17

现在这给了我一个大小为3的样本,但是我如何生成100,000个呢?我们也用过

N<-20 #size of the population we could choose from
n<- 3
x <- runif(N)
pi<-n*x/sum(x)

但我不知道出了什么问题。任何建议将不胜感激,谢谢。

3 个答案:

答案 0 :(得分:4)

您的问题激发了我尝试使用带有 -replacement的samples- 上的递归来编写多次采样 - 无替换的实现。

NS表示所需样本的数量,并NE从每个样本的输入集中选择的元素数量,我的想法是尝试避免循环{ {1}} NS次调用,这对于大型sample()来说非常耗时。相反,我们可以首先运行单个样本调用,将NS替换为,并考虑代表每个样本的“第一选择”。然后,对于每个唯一选择,我们可以通过所选元素减少输入集(和概率加权向量),并递归直到我们达到NS级别。通过组合每个(子)样本,我们可以生成一个矩阵,其行每个都包含一个样本,而无需替换输入集中的NE值。

NE

演示:

samplesNoReplace <- function(NS,set,NE=length(set),prob=NULL) {
    if (NE>1L) {
        inds <- sample(seq_along(set),NS,T,prob);
        uris <- split(seq_len(NS),inds);
        us <- as.integer(names(uris));
        res <- base::matrix(set[inds],NS,NE);
        for (ui in seq_along(uris)) {
            u <- us[ui];
            ris <- uris[[ui]];
            res[ris,-1L] <- samplesNoReplace(length(ris),set[-u],NE-1L,prob[-u]);
        }; ## end for
    } else {
        res <- base::matrix(sample(set,NS,T,if (length(set)==1L) NULL else prob),ncol=1L);
    }; ## end if
    res;
}; ## end samplesNoReplace()

基准

set.seed(10L); samplesNoReplace(10L,1:5,3L,c(10,2,2,2,1));
##       [,1] [,2] [,3]
##  [1,]    1    3    2
##  [2,]    1    4    3
##  [3,]    1    2    4
##  [4,]    3    2    1
##  [5,]    1    3    2
##  [6,]    1    4    2
##  [7,]    1    4    2
##  [8,]    1    2    5
##  [9,]    3    1    2
## [10,]    1    2    5
library(microbenchmark);

bgoldst <- function() samplesNoReplace(NS,set,NE,prob);
akrun <- function() { N1 <- seq_len(NS); N <- length(set); lapply(N1, function(i) sample(set, size =NE, replace=FALSE,prob)); };
khashaa <- function() { replicate(NS, sample(set, NE,prob=prob), simplify = FALSE); };
## OP's case (100k samples, smallish set, smaller subset)
set.seed(1L);
NS <- 1e5L; set <- 1:20; NE <- 3L; prob <- runif(length(set));

microbenchmark(times=5L,bgoldst(),akrun(),khashaa());
## Unit: milliseconds
##       expr      min        lq      mean    median        uq      max neval
##  bgoldst()  40.9888  42.69257  46.33044  46.68856  47.40488  53.8774     5
##    akrun() 547.3142 564.94249 599.96134 625.07602 631.19658 631.2774     5
##  khashaa() 501.1226 521.14871 531.50227 524.65247 549.47600 561.1116     5
## 10k samples, large set, small subset
set.seed(1L);
NS <- 1e4L; set <- 1:1000; NE <- 5L; prob <- runif(length(set));

microbenchmark(times=5L,bgoldst(),akrun(),khashaa());
## Unit: milliseconds
##       expr       min        lq      mean    median        uq       max neval
##  bgoldst() 2716.1904 2722.8242 2756.9302 2731.2763 2753.5668 2860.7935     5
##    akrun()  682.0505  688.3639  691.3169  689.6165  693.9692  702.5842     5
##  khashaa()  684.5865  689.2030  698.8313  693.0822  696.1211  731.1638     5
## 1k samples, large set, large subset
set.seed(1L);
NS <- 1e3L; set <- 1:1000; NE <- 500L; prob <- runif(length(set));

microbenchmark(times=1L,bgoldst(),akrun(),khashaa());
## Unit: milliseconds
##       expr        min         lq       mean     median         uq        max neval
##  bgoldst() 74478.4313 74478.4313 74478.4313 74478.4313 74478.4313 74478.4313     1
##    akrun()   350.7270   350.7270   350.7270   350.7270   350.7270   350.7270     1
##  khashaa()   353.2574   353.2574   353.2574   353.2574   353.2574   353.2574     1
## 1M samples, small set, necessarily small subset
set.seed(1L);
NS <- 1e6L; set <- 1:4; NE <- 4L; prob <- runif(length(set));

microbenchmark(times=5L,bgoldst(),akrun(),khashaa());
## Unit: milliseconds
##       expr       min        lq      mean    median        uq       max neval
##  bgoldst()  502.0865  519.1875  602.5631  627.6124  648.3831  715.5459     5
##    akrun() 5450.3987 5653.0774 5817.0921 5799.4497 5987.0575 6195.4771     5
##  khashaa() 5301.3673 5667.8592 5683.3805 5744.1461 5824.8801 5878.6497     5

这种模式非常有趣,我认为很容易解释。我的函数优于许多样本,小集和小子集,因为覆盖所有可能(子)样本分支所需的递归非常少,而循环解决方案必须迭代并对每个样本进行## 10M samples, small set, necessarily small subset set.seed(1L); NS <- 1e7L; set <- 1:4; NE <- 4L; prob <- runif(length(set)); microbenchmark(times=1L,bgoldst(),akrun(),khashaa()); ## Unit: seconds ## expr min lq mean median uq max neval ## bgoldst() 5.023389 5.023389 5.023389 5.023389 5.023389 5.023389 1 ## akrun() 75.891354 75.891354 75.891354 75.891354 75.891354 75.891354 1 ## khashaa() 69.422056 69.422056 69.422056 69.422056 69.422056 69.422056 1 调用。但是我的函数严重地表现为较少的样本,较大的集合和较大的子集,因为循环解决方案没有很多迭代要完成,并且(子)样本分支树随着每个新选择呈指数增长。因此,我的函数仅适用于许多样本,小集和小子集的情况,顺便说一下,它非常准确地描述了您的示例用例。

当然,即使对于他们最不利的时间,循环解决方案仍然可以在我的功能的大约一个数量级内正常运行。此外,在任何情况下都不太可能需要数百万个小集子集的样本。所以,为了简单起见,我不认为完全忽略这个解决方案是不合理的,并且总是使用循环方法。

答案 1 :(得分:2)

我们可以通过循环序列

来使用lapply
N1 <- seq_len(100000)
N <- 20
lapply(N1, function(i) sample(N, size =3, replace=FALSE))  

答案 2 :(得分:0)

我已经尝试了replicate命令和1apply,两者都给了我100个大小为3的样本,数字1到20,这很好,但现在我想能够计算每个数字出现的频率。据我所知,例如,9可能会出现100,000次,在所有100,000个3样本中,但更有可能发生在大约二十分之一的时间。因此,如果我每次有3万个3位数的样本,那么所有数字的总数应该是300,000,因为为了论证,R给了我100,000个九,其中9个恰好在每个样本中,然后有两个所有其他数字都剩下十万个地方。我把这个函数称为s,并试过了 count1&lt; - length(其中(s == 2)); count1 ,但是这样说 错误,其中(s == 1):(列表)对象无法强制键入&#39; double&#39; , 但我不明白这意味着什么。我如何要求R给我一个准确计算所有的,所有两个等等,我假设他们的总数应该总和为300,000,因为我们最终得到300,000个数字。谢谢。克里斯莉莉。