动机:我目前正在尝试重新考虑我的编码,例如在可能的情况下排除for循环。使用传统的for循环可以很容易地解决下面的问题,但我想知道R是否有可能利用apply-family来使问题更容易。
问题:我有一个矩阵,比如n x k
(index.starts
矩阵)和两个起始和终止索引矩阵,称为index.stops
和{{1 }}, 分别。它们的大小为n x B
,对于某个整数index.stops = index.starts + m
,它保持m
。每个index.starts[i,j]
和index.stops[i,j]
对需要X
作为X[ (index.starts[i,j]:index.stops[i,j]),]
。即,他们应该在其索引范围内选择X
的所有行。
我可以使用其中一个应用函数来解决这个问题吗?
应用程序 :(对于理解我的问题不一定很重要。)如果您感兴趣,那么在时间序列应用程序中使用块的自举应用程序需要这样做。 X
代表原始样本。 index.starts
被抽样为replicate(repetitionNumber, sample.int((n-r), ceiling(n/r), replace=TRUE))
,index.stops
被获取为index.stop = index.starts + m
。我最终想要的是X
行的集合。特别是,我想从repetitionNumber
重新采样m
次r
长度为X
的块。
示例:
#generate data
n<-100 #the size of your sample
B<-5 #the number of columns for index.starts and index.stops
#and equivalently the number of block bootstraps to sample
k<-2 #the number of variables in X
X<-matrix(rnorm(n*k), nrow=n, ncol = k)
#take a random sample of the indices 1:100 to get index.starts
r<-10 #this is the block length
#get a sample of the indices 1:(n-r), and get ceiling(n/r) of these
#(for n=100 and r=10, ceiling(n/r) = n/r = 10). Replicate this B times
index.starts<-replicate(B, sample.int((n-r), ceiling(n/r), replace=TRUE))
index.stops<-index.starts + r
#Now can I use apply-functions to extract the r subsequent rows that are
#paired in index.starts[i,j] and index.stops[i,j] for i = 1,2,...,10 = ceiling(n/r) and
#j=1,2,3,4,5=B ?
答案 0 :(得分:1)
这可能比你想要/需要的更复杂,但这是第一种方法。只要评论一下,如果这对您有任何帮助,我很乐意提供帮助。
我的方法使用(多个)* apply-functions。第一个lapply“循环”超过1:B的情况,它首先计算起点和终点,它们被合并到take.rows(带子集数)。接下来,初始矩阵由take.rows(并在列表中返回)进行子集化。作为最后一步,对子集化矩阵的每列采用标准偏差(作为虚函数)。
代码(评论很重)看起来像这样:
# you can use lapply in parallel mode if you want to speed up code...
lapply(1:B, function(i){
starts <- sample.int((n-r), ceiling(n/r), replace=TRUE)
# [1] 64 22 84 26 40 7 66 12 25 15
ends <- starts + r
take.rows <- Map(":", starts, ends)
# [[1]]
# [1] 72 73 74 75 76 77 78 79 80 81 82
# ...
res <- lapply(take.rows, function(subs) X[subs, ])
# res is now a list of 10 with the ten subsets
# [[1]]
# [,1] [,2]
# [1,] 0.2658915 -0.18265235
# [2,] 1.7397478 0.66315385
# ...
# say you want to compute something (sd in this case) you can do the following
# but better you do the computing directly in the former "lapply(take.rows...)"
res2 <- t(sapply(res, function(tmp){
apply(tmp, 2, sd)
})) # simplify into a vector/data.frame
# [,1] [,2]
# [1,] 1.2345833 1.0927203
# [2,] 1.1838110 1.0767433
# [3,] 0.9808146 1.0522117
# ...
return(res2)
})
这是否指向正确的方向/给你答案?