以可伸缩的方式引导data.table中的多个列

时间:2016-08-17 06:51:38

标签: r data.table bootstrapping

这是对this之一的跟进问题。在原始问题中,OP希望在已修复的两列x1x2上执行引导:

set.seed(1000)
data <- as.data.table(list(x1 = runif(200), x2 = runif(200), group = runif(200)>0.5))
stat <- function(x, i) {x[i, c(m1 = mean(x1), m2 = mean(x2))]}
data[, list(list(boot(.SD, stat, R = 10))), by = group]$V1

但是,我认为通过将它们视为组来处理任意数量的列,可以很好地扩展此问题。例如,让我们使用iris数据集。假设我想计算每个物种的所有四个维度的自助均值。我可以使用melt来翻转数据,然后使用Speciesvariable组合一次性获得平均值 - 我认为这种方法可以很好地扩展。

data(iris)
iris = data.table(iris)
iris[,mean(Sepal.Length),by=Species]
iris[,ID:=.N,]
iris_deep = melt(iris
                 ,id.vars = c("ID","Species")
                 ,measure.vars = c("Sepal.Length","Sepal.Width","Petal.Length","Petal.Width"))
#define a mean bootstrap function
stat <- function(x, i) {x[i, m=mean(value),]}
iris_deep[, list(list(boot(.SD, stat, R = 100))), by = list(Species,variable)]$V1

这是我尝试这样做的。然而,自举部分似乎不起作用。由于R抛出以下错误:

Error in mean(value) : object 'value' not found

有人可以解决这个问题吗?

2 个答案:

答案 0 :(得分:1)

我尝试了这个(添加了括号m=mean(value)的大括号),它似乎有效:

stat <- function(x, i) {x[i, (m=mean(value))]}

答案 1 :(得分:0)

我们可以充分利用每个引导程序,并为每个组中的每个变量计算平均值,而不必为每个变量重新运行引导程序。

因此,如果我们这样做,它将计算每个变量的平均值:

iris = data.table(iris)
iris[sample(nrow(iris),replace=TRUE),lapply(.SD,mean,na.rm=TRUE),by=Species]

由于引导需要向量/矩阵输出,因此我们需要修改上面的输出,并提供向量的名称:

d = function(dat,ind){
 k = dat[ind,lapply(.SD,mean,na.rm=TRUE),by=Species]
 k_vec = unlist(k[,-1])
 names(k_vec) = paste(rep(colnames(k)[-1],each=nrow(k)),rep(k$Species,(ncol(k)-1)),sep="_")
 k_vec
}

d(iris,sample(nrow(iris),replace=TRUE))
 Sepal.Length_versicolor  Sepal.Length_virginica     Sepal.Length_setosa 
              5.8784314               6.4851852               4.9688889 
 Sepal.Width_versicolor   Sepal.Width_virginica      Sepal.Width_setosa 
              2.7392157               2.9814815               3.3977778 
Petal.Length_versicolor  Petal.Length_virginica     Petal.Length_setosa 
              4.1980392               5.5037037               1.4644444 
 Petal.Width_versicolor   Petal.Width_virginica      Petal.Width_setosa 
              1.2960784               2.0944444               0.2333333

并使用strata = iris$Species引导以确保对物种进行均匀采样:

bo_strata = boot(iris,d,R=1000,strata=iris$Species)

我们可以将这种方法的分布与问题中的分布进行比较:

stat <- function(x, i) {x[i, (m=mean(value))]}
bo_melt = iris_deep[, list(list(boot(.SD, stat, R = 1000))), by = list(Species,variable)]$V1

par(mfrow=c(4,3))
par(mar=c(3,3,3,3))
for(i in 1:ncol(bo_strata$t)){
plot(density(bo_strata$t[,i]),main=names(bo_strata$t0)[i],col="#43658b")
lines(density(bo_melt[[i]]$t),col="#ffa372")
legend("topright",fill=c("#43658b","#ffa372"),c("strata","other"))
}

enter image description here