如何在purrr中的多个数据集上拟合多个模型?

时间:2017-09-20 22:50:08

标签: r purrr

我有以下的tibble

    tribble(
  ~func, ~models, ~data,
  'lm'  ,  formula = mpg ~ disp, mtcars,
  'lm'  ,  formula = mpg ~ disp, filter(mtcars, carb < 4)
)

现在,我想在数据集func上将models中指定的模型类型与公式data相匹配。我试着像这样使用invoke,但它不起作用:

   tribble(
  ~func, ~models, ~data,
  'lm'  ,  formula = mpg ~ disp, mtcars,
  'lm'  ,  formula = mpg ~ disp, filter(mtcars, carb < 4)
)%>% invoke_map(func, list(models, data))

2 个答案:

答案 0 :(得分:3)

如果每个模型的参数列表都在一个变量中,

invoke_map可以处理这样的数据集。

这看起来像下面这样。注意使用花括号,这样我就可以从管道链中的数据集中调用每一列。

tribble(~func, ~params,
        'lm'  ,  list(formula = mpg ~ disp, data = mtcars),
        'lm'  ,  list(formula = mpg ~ disp, data = filter(mtcars, carb < 4) ) ) %>% 
     {invoke_map(.$func, .$params)}

如果您需要从当前的tribble中使用多列参数转换为参数作为单个列中的列表,您可以执行类似

的操作
tribble(~func, ~models, ~data,
        'lm'  ,  formula = mpg ~ disp, mtcars,
        'lm'  ,  formula = mpg ~ disp, filter(mtcars, carb < 4) ) %>%
     mutate(params = pmap(list(models, data), list) ) %>% 
     {invoke_map(.$func, .$params)}

如果您的最终目标是将模型添加到数据集中,则可以在invoke_map中使用mutate

tribble(~func, ~models, ~data,
        'lm'  ,  formula = mpg ~ disp, mtcars,
        'lm'  ,  formula = mpg ~ disp, filter(mtcars, carb < 4) ) %>%
     mutate(params = pmap(list(models, data), list),
            fit = invoke_map(func, params ) )

答案 1 :(得分:1)

我们想要建立一个包含所有并行参数的列表列表,然后调用一个包含所有这些参数的函数。我们将pmap执行此操作。 方便的是,modelr包具有fit_with,它包含建模函数,公式和数据集。由于pmap会返回列表列表,因此我们将flatten列入数据框的列表列。

tribble(~funcs,  ~models,       ~dat,
        glm,    "len ~ dose",   ToothGrowth,
        lm,     "len ~ dose",   filter(ToothGrowth, supp == "VC")) %>% 
  mutate(fit = flatten(pmap(.l = list(.f = funcs, .formulas = models, data = dat), 
                            .f = modelr::fit_with))) 
# A tibble: 2 x 4
   funcs     models                   dat       fit
  <list>      <chr>                <list>    <list>
1  <fun> len ~ dose <data.frame [60 x 3]> <S3: glm>
2  <fun> len ~ dose <data.frame [30 x 3]>  <S3: lm>

您可以在broom的各种模型整理功能中使用列表列 fit

library(broom)

tribble(~funcs,  ~models,       ~dat,
        glm,    "len ~ dose",   ToothGrowth,
        lm,     "len ~ dose",   filter(ToothGrowth, supp == "VC")) %>% 
  mutate(fit = flatten(pmap(.l = list(.f = funcs, .formulas = models, data = dat), 
                            .f = modelr::fit_with))) %>% 
  do(map_dfr(.$fit, tidy, .id = "dataset"))
  dataset        term  estimate std.error statistic      p.value
1       1 (Intercept)  7.422500 1.2600826  5.890487 2.064211e-07
2       1        dose  9.763571 0.9525329 10.250114 1.232698e-14
3       2 (Intercept)  3.295000 1.4270601  2.308943 2.854201e-02
4       2        dose 11.715714 1.0787561 10.860392 1.509369e-11

更新

另一种方法,与第一种方法更相似:

tribble(~funcs,  ~models,       ~dat,
        "glm",    len ~ dose,   ToothGrowth,
        "lm",     len ~ dose,   filter(ToothGrowth, supp == "VC")) %>% 
  rowwise() %>% 
  mutate(fit = invoke_map(.f = funcs, .x = list(list(formula = models, data = dat)))) %>% 
  {map_dfr(.$fit, tidy, .id = "dataset")}

请注意,在函数名称周围使用引号并使用rowwise来使列表列表( .x )的每个列表元素长度为1。