在以下代码"重量"是一个庞大的权重集矩阵。该矩阵由1000行和4列组成。每行是一组权重(每行中元素的总和等于1)。
另外,有四个对象,我想根据每个权重集选择其中一个。换句话说,应该对所有权重集重复这种随机选择。
现在我已用for
解决了问题。但是有没有更有效的方法在R中编码呢?
y <- c("a", "b", "c", "d")
for(i in 1:nrow(Weight)){
selection[i] <- sample(y, 1, prob=Weight[i,]) #selection is a vector with the same number of rows as Weight
}
答案 0 :(得分:5)
更有效的方法是首先计算权重的行方式累积总和,然后在0
和1
之间绘制一个数字,并查看它在该累积总和中的位置。这样,您只需要对runif
进行一次调用即可获得随机数据,而使用其他方法进行1000
调用。
Weight <- matrix(sample(1:100, 1000 * 4, TRUE), 1000, 4)
x <- runif(nrow(Weight))
cumul.w <- Weight %*% upper.tri(diag(ncol(Weight)), diag = TRUE) / rowSums(Weight)
i <- rowSums(x > cumul.w) + 1L
selection <- y[i]
另请注意我是如何通过乘以三角矩阵而不是使用较慢的apply(Weight, 1, cumsum)
来计算累积和。一切都是矢量化的,所以它应该比使用apply
或for
循环更快。
与apply
和for
进行基准比较:
f_runif <- function(Weight, y) {
x <- runif(nrow(Weight))
cumul.w <- Weight %*% upper.tri(diag(ncol(Weight)), diag = TRUE) /
rowSums(Weight)
i <- rowSums(x > cumul.w) + 1L
y[i]
}
f_for <- function(Weight, y) {
selection <- rep(NA, nrow(Weight))
for(i in 1:nrow(Weight)){
selection[i] <- sample(y, 1, prob=Weight[i,])
}
}
f_apply <- function(Weight, y) {
apply(Weight, 1, function(w)sample(y, 1, prob=w))
}
y <- c("a", "b", "c", "d")
Weight <- matrix(sample(1:100, 1000 * 4, TRUE), 1000, 4)
library(microbenchmark)
microbenchmark(f_runif(Weight, y),
f_for (Weight, y),
f_apply(Weight, y))
# Unit: microseconds
# expr min lq median uq max neval
# f_runif(Weight, y) 223.635 231.111 274.531 281.2165 1443.208 100
# f_for(Weight, y) 10220.674 11238.660 11574.039 11917.1610 14583.028 100
# f_apply(Weight, y) 9006.974 10016.747 10509.150 10879.9245 27060.189 100
答案 1 :(得分:2)
将sample
包装到一个只允许传递一个参数的函数中,一行来自Weight
:
myfun <- function(w) {
sample(y, 1, prob=w)
}
然后您可以使用其中一个申请系列:
apply(Weight, 1, myfun)
但是,只要您预先分配selection
,您的方法效率就不会非常低。