基本上,我们的想法是让值n=10,20,30,...100
取10,000个随机样本的平均值,节省10,000个以供日后使用的方法。
在我更习惯使用的语言中,我会使用每个n
作为键创建一个hashmap,并使用means列表作为值。
以javascript为例:
var mydata
var map = {}
for (int i = 10; i <= 100; i += 10 ) {
map[i] = [] // create list
for (int j = 0; j < 10000; j++) {
map[i][j] = mean(sample(mydata, i))
}
}
现在我尝试在R中这样做(这是我第一次使用它),我最终得到了:
hashmap <- new.env()
sunspots <- read.table("sunspots.txt")
for (i in seq(10, 100, by=10)) {
hashmap[[i]] <- c()
for (j in 1:10000) {
hashmap[[i]][j] <- mean(sample(sunspots$x, i))
}
}
然而,这会引发错误:
wrong args for environment subassignment
即使它没有抛出这个错误,我也不能完全确定我是否以正确的方式接近它。
有人可以帮我理解正确的方法吗?
答案 0 :(得分:2)
这里的问题是i
是一个数字,环境必须用字符串键入。因此,当i
变量用于索引hashmap
时,可以通过简单的as.character()
强制解决您的直接问题。
我还建议你将内部循环重构为向量化函数调用,例如replicate()
。以下是我将如何做到这一点:
set.seed(1L);
test.data <- 1:200;
N <- 3L;
e <- new.env();
for (i in seq(10L,100L,10L)) e[[as.character(i)]] <- replicate(N,mean(sample(test.data,i)));
结果:
ls(e);
## [1] "10" "100" "20" "30" "40" "50" "60" "70" "80" "90"
for (i in seq(10L,100L,10L)) print(e[[as.character(i)]]);
## [1] 108.3 109.4 82.4
## [1] 108.50 93.65 106.20
## [1] 103.3333 96.0000 101.2333
## [1] 98.075 95.250 83.275
## [1] 106.68 97.48 107.34
## [1] 97.48333 105.95000 98.76667
## [1] 101.8857 102.4857 114.6000
## [1] 99.5875 107.0875 96.0750
## [1] 92.9000 103.0889 100.7889
## [1] 91.19 99.80 101.57
您可以将N
更改为10000,将test.data
更改为sunspots
以获取真实数据。
此外,这是一个产生矩阵输出的替代方法,它围绕sapply()
的便捷功能构建,它返回来自FUN()
的多元素返回值的矩阵:
set.seed(1L);
sapply(seq(10L,100L,10L),function(i) replicate(N,mean(sample(test.data,i))));
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## [1,] 108.3 108.50 103.3333 98.075 106.68 97.48333 101.8857 99.5875 92.9000 91.19
## [2,] 109.4 93.65 96.0000 95.250 97.48 105.95000 102.4857 107.0875 103.0889 99.80
## [3,] 82.4 106.20 101.2333 83.275 107.34 98.76667 114.6000 96.0750 100.7889 101.57
答案 1 :(得分:1)
这不是一样的,但更简单,更易读吗?
set.seed(123)
N = 10000
sunspots <- rnorm(N, 10, 2)
sim <- lapply(seq(10, 100, by=10), function(i){
sapply(1:N, function(j){
mean(sample(sunspots, i))
})
})
lapply(sim, head)
这是有道理的,因为复制只是一个sapply
电话。
> replicate
function (n, expr, simplify = "array")
sapply(integer(n), eval.parent(substitute(function(...) expr)),
simplify = simplify)
<bytecode: 0x19b0b7108>
<environment: namespace:base>
编辑
如评论中所述。
simulation <- function(data, i){
sapply(1:N, function(j) mean(sample(data, i)))
}
sim <- lapply(seq(10, 100, by=10), function(i) simulation(sunspots, i))
# This would give the same output.
do.call(cbind, lapply(sim, head))
# You could potentially use sapply on the first level also.
sim <- sapply(seq(10, 100, by=10), function(i) simulation(sunspots, i))
str(sim)