我正在尝试从数字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)
但我不知道出了什么问题。任何建议将不胜感激,谢谢。
答案 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个数字。谢谢。克里斯莉莉。