bootstrap分组并计算统计
bootstrap by group and calculate statistics
我正在尝试 bootstrap 一些模型拟合,然后计算统计数据,而不必每次都重新运行模型。如果我在第一个 do()
中计算 r2,我可以做得很好,但我想知道如何访问数据。
library(dplyr)
library(tidyr)
library(modelr)
library(purrr)
allmdls <-
mtcars %>%
group_by(cyl) %>%
do({
datsplit=crossv_mc(.,10)
mdls=list(map(datsplit$train, ~glm(hp~disp,data=.,family=gaussian(link='identity'))))
data_frame(datsplit=list(datsplit),mdls)
})
现在是这样的:
allmdls %>%
by_slice(dmap,.f=map2_dbl(.$mdls,.$datsplit$test,rsquare))
但我得到
Error: .y
is not a vector (NULL)
或
allmdls %>%
group_by(cyl) %>%
do({
map2_df(.x=.$mdls, .y=.$datsplit, .f=map2_dbl(.x=.x,.y=.y$test,.f=rsquare))
})
Error in map2_dbl(.x = .x, .y = .y$test, .f = rsquare) : object
'.x' not found
我似乎无法正确理解语法。
帮忙?
谢谢
编辑:
感谢@aosmith 的评论,我创建了一个更简单的解决方案:
mtcars %>%
group_by(cyl) %>%
do({
datplit=crossv_mc(.,10) %>%
mutate(mdls=map(train, ~glm(hp~disp,data=.)),
r2=map2_dbl(mdls,test,rsquare)
pctmae=map2_dbl(mdls,test,function(model,data) {mae(model,data)/mean(model$model$hp,na.rm=T)*100})
)
})
一种选择是在 mutate
中使用 map2
。因为您使用的是列表的列表,所以我最终使用嵌套的 map2
s 来访问最里面的列表。我通过 map(datsplit, "test")
提取了 test
数据,因为美元符号运算符和提取括号都不适合我。
mutate(allmdls, rsq = map2(mdls, map(datsplit, "test"), ~map2_dbl(.x, .y, rsquare)))
这是另一个避免嵌套列表的选项:
mtcars %>%
split(.$cyl) %>%
map_df(crossv_mc, 10, .id = "cyl") %>%
mutate(models = map(train, ~glm(hp ~ disp, data = .x)),
rsq = map2_dbl(models, test, rsquare))
@aosmith 回答了我的问题,但总体来说这是一个更简单的解决方案
mtcars %>%
group_by(cyl) %>%
do({
datplit=crossv_mc(.,10) %>%
mutate(mdls=map(train, ~glm(hp~disp,data=.)),
r2=map2_dbl(mdls,test,rsquare)
pctmae=map2_dbl(mdls,test,function(model,data) {mae(model,data)/mean(model$model$hp,na.rm=T)*100})
)
})
我正在尝试 bootstrap 一些模型拟合,然后计算统计数据,而不必每次都重新运行模型。如果我在第一个 do()
中计算 r2,我可以做得很好,但我想知道如何访问数据。
library(dplyr)
library(tidyr)
library(modelr)
library(purrr)
allmdls <-
mtcars %>%
group_by(cyl) %>%
do({
datsplit=crossv_mc(.,10)
mdls=list(map(datsplit$train, ~glm(hp~disp,data=.,family=gaussian(link='identity'))))
data_frame(datsplit=list(datsplit),mdls)
})
现在是这样的:
allmdls %>%
by_slice(dmap,.f=map2_dbl(.$mdls,.$datsplit$test,rsquare))
但我得到
Error:
.y
is not a vector (NULL)
或
allmdls %>%
group_by(cyl) %>%
do({
map2_df(.x=.$mdls, .y=.$datsplit, .f=map2_dbl(.x=.x,.y=.y$test,.f=rsquare))
})
Error in map2_dbl(.x = .x, .y = .y$test, .f = rsquare) : object '.x' not found
我似乎无法正确理解语法。
帮忙? 谢谢
编辑: 感谢@aosmith 的评论,我创建了一个更简单的解决方案:
mtcars %>%
group_by(cyl) %>%
do({
datplit=crossv_mc(.,10) %>%
mutate(mdls=map(train, ~glm(hp~disp,data=.)),
r2=map2_dbl(mdls,test,rsquare)
pctmae=map2_dbl(mdls,test,function(model,data) {mae(model,data)/mean(model$model$hp,na.rm=T)*100})
)
})
一种选择是在 mutate
中使用 map2
。因为您使用的是列表的列表,所以我最终使用嵌套的 map2
s 来访问最里面的列表。我通过 map(datsplit, "test")
提取了 test
数据,因为美元符号运算符和提取括号都不适合我。
mutate(allmdls, rsq = map2(mdls, map(datsplit, "test"), ~map2_dbl(.x, .y, rsquare)))
这是另一个避免嵌套列表的选项:
mtcars %>%
split(.$cyl) %>%
map_df(crossv_mc, 10, .id = "cyl") %>%
mutate(models = map(train, ~glm(hp ~ disp, data = .x)),
rsq = map2_dbl(models, test, rsquare))
@aosmith 回答了我的问题,但总体来说这是一个更简单的解决方案
mtcars %>%
group_by(cyl) %>%
do({
datplit=crossv_mc(.,10) %>%
mutate(mdls=map(train, ~glm(hp~disp,data=.)),
r2=map2_dbl(mdls,test,rsquare)
pctmae=map2_dbl(mdls,test,function(model,data) {mae(model,data)/mean(model$model$hp,na.rm=T)*100})
)
})