Начальная загрузка нескольких столбцов в data.table масштабируемым способом R

Это дополнительный вопрос к этому. В исходном вопросе OP хотел выполнить начальную загрузку для двух фиксированных столбцов x1 и x2:

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, чтобы перевернуть данные, а затем использовать комбинацию Species, variable, чтобы получить среднее значение за один раз — я думаю, что этот подход будет хорошо масштабироваться.

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

Может кто-нибудь, пожалуйста, взломать это?


person sriramn    schedule 17.08.2016    source источник


Ответы (2)


Я попробовал это (с добавленными фигурными скобками, окружающими m=mean(value)), и, похоже, это работает:

stat <- function(x, i) {x[i, (m=mean(value))]}
person renato vitolo    schedule 17.08.2016

Мы можем полностью использовать каждый бутстрап и вычислять среднее значение для каждой переменной в каждой группе вместо повторного запуска бутстрапа для каждой переменной.

Итак, если мы сделаем что-то подобное, он вычислит среднее значение для каждой переменной:

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"))
}

введите здесь описание изображения

person StupidWolf    schedule 02.09.2020