有效地对数据帧进行采样,避免循环

时间:2012-12-28 15:06:02

标签: performance r loops sampling

我有一个数据框,其中包含第一列(experiment.id),其余列是与此实验ID关联的值。每行都是唯一的实验ID。我的数据框有10 in - 10⁵的列。

data.frame(experiment.id=1:100, v1=rnorm(100,1,2),v2=rnorm(100,-1,2) )

此数据框是我的示例空间的来源。我想做的是,每个独特的实验.id(行)随机抽样(替换)与该id相关联的值v1,v2,....,v10000之一,并构建样本s1。在每个样本s1中,表示所有实验ID。

最终我想要执行10⁴个样本,s1,s2,....,s10⁴并计算一些统计数据。

执行此采样过程的最有效方式(计算)。我想尽可能避免循环。

更新 我的问题不是关于采样而是存储样本。我想我真正的问题是,除了

之外,还有更快的方法来执行上述操作
d<-data.frame(experiment.id=1:1000, replicate (10000,rnorm(1000,100,2)) )
results<-data.frame(d$experiment.id,replicate(n=10000,apply(d[,2:10001],1,function(x){sample(x,size=1,replace=T)})))

3 个答案:

答案 0 :(得分:3)

这是一个选择其中一列(不包括第一列)的表达式。它不会复制第一列,您需要将其作为单独的步骤提供。

对于数据框d

d[matrix(c(seq(nrow(d)), sample(ncol(d)-1, nrow(d), replace=TRUE)+1), ncol=2)]

这是一个样本。要获得N个样本,只需乘以选择(如John的答案):

mm <- matrix(c(rep(seq(nrow(d)), N), sample(ncol(d)-1, nrow(d)*N, replace=TRUE)+1), ncol=2)

result <- matrix(d[mm], ncol=N)

但是你会遇到记忆问题。

答案 1 :(得分:2)

可以不做任何循环。如果将第一个列之后的列转换为矩阵,则这很容易,因为矩阵可以作为[行,列]或顺序地作为它的底层向量来寻址。

mat <- as.matrix(datf[,-1])
nr <- nrow(mat); nc <- ncol(mat)
sel <- sample( 1:nc, nr, replace = TRUE )
sel <- sel + ((1:nr)-1) * nc
x <- t(mat)[sel]
seldatf <- data.frame( datf[,1], x = x )

现在,要获得大量样本,只需乘以相同的逻辑即可。

ns <- 10 # number of samples / row
sel <- sample(1:nc, nr * ns, replace = TRUE )
sel <- sel + rep(((1:nr)-1) * nc, each = ns)
x <- t(mat)[sel]
seldatf <- cbind( datf[,1],  data.frame(matrix(x, ncol = ns, byrow = TRUE)) )

如果你要设置ns <- 1e5并且你有很多行,那么它可能是一个非常大的数据框架。您可能需要注意内存不足。出于可读性原因,我做了一些不必要的复制。您可以消除内存和速度,因为一旦您使用大量内存,您将交换正在运行的其他程序。那很慢。您不必分配和保存x,mat甚至sel。不这样做的结果将为您提供尽可能快的答案。

答案 2 :(得分:2)

最短且最易读的恕我直言仍然使用apply,但充分利用sample被矢量化的事实:

results <- data.frame(experiment.id = d$experiment.id,
                      t(apply(d[, -1], 1, sample, 10000, replace = TRUE)))

如果需要的3秒钟太慢,那么我建议您使用矩阵索引。