提问人:heikeehee 提问时间:11/16/2023 更新时间:11/17/2023 访问量:38
提高自举功能的效率
Improve efficiency of bootstrap function
问:
我有一个大数据帧,我想从中对每列进行随机抽样。我想多次采样并将结果的总和存储在新的数据帧中。
我的数据帧如下所示:
library(microbenchmark)
library(plyr)
library(tidyverse)
set.seed(123)
df <- data.frame(matrix(sample(0:10, replace = T), nrow = 1000, ncol=60))
我编写了一个函数来从我的数据帧中采样并计算我的统计数据。
rd <- function(x) sample(x, size = N, replace =TRUE)
N <- nrow(df)
sampling <- function(df){
df_s <- apply(df, 2, rd)
df_f <- df_s %>%
as.data.frame() %>%
summarise_if(is.numeric, sum)
}
我想复制这 10000 并将汇总统计信息保存在新的数据帧中。
reps <- 10
df_sums <- plyr::rdply(reps, sampling(df))
但是,单独运行此代码 100 次似乎效率非常低,使用我的原始数据集需要更长的时间。
microbenchmark(sampling(df), times = 100)
有什么建议如何使它更有效率,以便我可以实际运行我的代码 10000 次?我尝试用 编写函数,但我无法让输出看起来像 一样整洁。replicate
rdply
答:
0赞
Robert Hacken
11/16/2023
#1
也许您不需要对单个列重新采样,但可以一次对整个数据帧进行重新采样。
sampling2 <- function(df) {
colSums(df[sample(nrow(df), replace=T), ])
}
df_sums <- t(replicate(100, sampling2(df)))
这工作得更快:
microbenchmark(sampling(df),
sampling2(df))
# Unit: milliseconds
# expr min lq mean median uq max neval cld
# sampling(df) 62.047601 64.451151 77.350142 69.629501 81.000350 476.3357 100 b
# sampling2(df) 1.427401 1.562552 1.954756 1.654052 1.906201 13.3865 100 a
请注意,使用这种方法会在一定程度上破坏 行中值的独立性。如果这将是一个问题,可以通过重新采样以下列来解决:df_sums
df_sums
df_sums <- apply(df_sums, 2, sample)
评论
0赞
jblood94
11/17/2023
这些样本在各列之间不会独立,例如,第一列的第 1 个值将始终与第二列的第 1 个值一起采样。
0赞
Robert Hacken
11/17/2023
@jblood94 没错,如果这对 OP 的应用程序来说是一个问题,他们总是可以对结果矩阵的行进行重采样。我可能应该更明确地说明这一点,谢谢!
0赞
heikeehee
11/17/2023
是的,我应该更清楚这一点(我希望我的代码正在这样做)。我想从每一列中随机抽取样本,这些样本独立于其他列,也独立于从中抽样的行。
0赞
jblood94
11/17/2023
#2
由于它是用替换进行采样的,因此您可以用内存换取速度。取 10k bootstrap 样本乘以每列的 1k 行 = 10M 样本,将它们放入 10k×1k 矩阵中并取行总和。示例矩阵在我 8 岁的笔记本电脑上需要 30 秒。
set.seed(123)
df <- data.frame(matrix(sample(0:10, 6e4, 1), 1e3, 60))
library(Rfast)
system.time(
sapply(df, \(x) rowsums(matrix(sample(x, 1e4*length(x), 1), 1e4)))
)
#> user system elapsed
#> 27.12 1.06 30.47
评论