modelr:交叉验证模型适合数据集中符合标准的所有变量

modelr: cross-validated model fitting for all variables in a dataset that match criterion

我有一个数据集,其中包含许多前缀为 "cat_" 的(因子)变量。

library(tidyverse)
library(modelr)
library(lazyeval)
library(purrr)

# create the dataset
df_foo = wakefield::r_data_frame(
  n = 100,
  wakefield::r_series(wakefield::r_sample, j = 5, name = "cat"),
  Y = wakefield::normal()
)

我希望能够使用 tidy 框架计算每个因子变量与响应变量的成对、k 折交叉验证回归 R2。

对于下面的几个变量,跨折叠计算这个很容易。

df_foo %>% 
  mutate_at(.funs = funs(as.factor), .cols = vars(starts_with("cat"))) %>% 
  crossv_kfold(k = 10, id = "id") %>% 
  mutate_(
    .dots = setNames(
      list(
        interp(
          quote(
            purrr::map_dbl(train, .f = function(train_data) {
          summary(stats::lm(Y ~ cat_1, data = train_data))$r.squared
        }))),
        interp(
          quote(
            purrr::map_dbl(train, .f = function(train_data) {
          summary(stats::lm(Y ~ cat_2, data = train_data))$r.squared
        })))
      ),
      nm = c("cat_1", "cat_2")
    )
  )

问题:


编辑:

以下代码获取每个变量的 R2,但不能将其展平为等于数据集中变量数的列数。

make_r2_variable = function(var_name, train_data) {
  summary(stats::lm(Y ~ var_name, data = train_data))$r.squared
}

make_r2 = function(train_data) {
  summarise_at(
    .tbl =  data.frame(train_data),
    .cols = vars(starts_with("cat_")),
    .funs = funs(make_r2_variable(., train_data = train_data))
  )

}

df_foo = df_foo %>% 
  mutate_at(.funs = funs(as.factor), .cols = vars(starts_with("cat"))) %>% 
  crossv_kfold(k = 10, id = "id") %>% 
  mutate(
    R2 = map(.x = train, .f = make_r2)
  ) 

我认为最紧凑的解决方案是:

make_r2_variable = function(var_name, train_data) {
  summary(stats::lm(Y ~ var_name, data = train_data))$r.squared
}

make_r2 = function(train_data) {
  summarise_at(
    .tbl =  data.frame(train_data),
    .cols = vars(starts_with("cat_")),
    .funs = funs(make_r2_variable(., train_data = train_data))
  )

}

df_foo = df_foo %>% 
  mutate_at(.funs = funs(as.factor), .cols = vars(starts_with("cat"))) %>% 
  crossv_kfold(k = 10, id = "id") %>% 
  mutate(
    R2 = map(.x = train, .f = make_r2)
  ) %>% 
  unnest(R2)

这基本上是我在编辑中加上 unnest 的解决方案。这基本上使用 map 改变 S3: resample 列,并在其中使用 mutate_at 循环匹配条件的列。由于 returns 一个 list/1D data.frame,因此需要调用 unnest