【问题标题】:Conditional mutate map lm within a nested data.frame嵌套 data.frame 中的条件变异映射 lm
【发布时间】:2021-04-16 15:52:58
【问题描述】:

我正在尝试使用嵌套 data.frame 和 map mutate 方法运行分层分析,以拟合特定层中略有不同的模型:

cars_nest <- mtcars %>%
  group_by(cyl) %>%
  nest()

model1 <- function(df) {
  lm(mpg ~ disp + wt, data = df)
}

model2 <- function(df) {
  lm(mpg ~ disp + wt + factor(vs), data = df)
}

cars_nest %>% 
  mutate(
    model = case_when(
      cyl == 8 ~ map(data, model1),
      cyl %in% c(4, 6) ~ map(data, model2)
    )
  )

我收到了错误

错误:mutate() 输入 model 有问题。 x 对比只能应用于具有 2 个或更多水平的因子 ℹ 输入modelcase_when(...)。 ℹ 错误发生在第 3 组:cyl = 8。

我认为这是由于 case_when 的矢量化操作,因为下面似乎确实有效。

cars_nest %>% 
  mutate(
    model = ifelse(cyl == 8, map(data, model1),
                   ifelse(cyl %in% c(4, 6), map(data, model2), NA)
    )
  )

有没有办法使用 case_when() 来完成这项工作?

注意:模型 2 中的因素是复制问题所必需的。在实际模型中,这是一个在第一层只有一个水平,在第二层有一个以上水平的因子。

【问题讨论】:

  • 和你的model2有关

标签: r dplyr tidyr purrr


【解决方案1】:

我们可以使用if/else

library(dplyr)
mtcars %>%
   nest_by(cyl) %>% 
   mutate(model = if(cur_group() == 8) list(model1(data)) else 
              list(model2(data))) %>% 
   ungroup

-输出

# A tibble: 3 x 3
#    cyl           data model   
#  <dbl> <list<tibble>> <list>
#1     4      [11 × 10] <lm>  
#2     6       [7 × 10] <lm>  
#3     8      [14 × 10] <lm>  

或者使用 OP 的代码

library(purrr)
cars_nest %>% 
  mutate(
    model = 
      if(cur_group() == 8) map(data, model1)
      else map(data, model2)
    )
# A tibble: 3 x 3
# Groups:   cyl [3]
#    cyl data               model 
#  <dbl> <list>             <list>
#1     6 <tibble [7 × 10]>  <lm>  
#2     4 <tibble [11 × 10]> <lm>  
#3     8 <tibble [14 × 10]> <lm>  

【讨论】:

  • @RaoulDuke 和 case_when,默认选项是 NA 并且有类型检查和结构检查
  • @AnoushiravanR 这是一个嵌套列表,但如果你拉模型cars_nest %&gt;% mutate(model = map2(cyl, data, ~ ifelse(.x %in% c(4, 6), model2(.y), model1(.y)))) %&gt;% pull(model),我会在那里得到 lm 结果
  • @akrun 我知道了,非常感谢。
  • @akrun 哦,没关系,我明白了。事实上,您不必回复任何评论或问题,因为我们都有自己的关注点,我不希望快速回复。我完全理解你的情况,我已经欠你的债,感谢你教给我的所有东西。只要有可能,就慢慢来。
  • @akrun 我很抱歉再次提出这么多问题。我希望有一天我能回报这个人情。
【解决方案2】:

您也可以使用以下解决方案,但是所有这些之间没有太大区别:

library(dplyr)
library(purrr)
library(broom)

cars_nest %>%
  mutate(model = ifelse(cyl %in% c(4, 6), map(data, ~ model2(.)), 
                        map(data, ~ model1(.))), 
         glance = map(model, ~ glance(.x))) %>%
  unnest(glance) %>%
  select(-data)

# A tibble: 3 x 14
# Groups:   cyl [3]
    cyl model r.squared adj.r.squared sigma statistic p.value    df logLik   AIC   BIC deviance
  <dbl> <lis>     <dbl>         <dbl> <dbl>     <dbl>   <dbl> <dbl>  <dbl> <dbl> <dbl>    <dbl>
1     6 <lm>      0.702         0.403  1.12      2.35  0.251      3  -7.78  25.6  25.3     3.78
2     4 <lm>      0.659         0.513  3.15      4.51  0.0461     3 -25.7   61.5  63.5    69.3 
3     8 <lm>      0.425         0.320  2.11      4.06  0.0477     2 -28.6   65.3  67.8    49.0 
# ... with 2 more variables: df.residual <int>, nobs <int>

【讨论】:

  • 正如亲爱的@akrun 刚才提到的,当我可以使用ifelseif_else 时,我个人从不使用case_when,因为它们更灵活。但这是个人选择,这只是我的意见。
  • if_else 也会进行一些类型检查。 case_whenif_else 是不错的选择。只是当这里返回的对象很复杂并且我们的逻辑条件长度是单行时
  • @akrun 你是绝对正确的。我只需要和他们一起体验更多的选择。我只是不知道map2 选项出了什么问题。
【解决方案3】:

只需从model2 中删除factor

model2 <- function(df) {
  lm(mpg ~ disp + wt + vs, data = df)
}

然后

cars_nest %>% 
  mutate(
    model = case_when(
      cyl == 8 ~ map(data, model1),
      cyl %in% c(4, 6) ~ map(data, model2)
    )
  ) %>% 
  print

结果

# A tibble: 3 x 3
# Groups:   cyl [3]
    cyl data                    model 
  <dbl> <list>                  <list>
1     6 <tibble[,10] [7 x 10]>  <lm>  
2     4 <tibble[,10] [11 x 10]> <lm>  
3     8 <tibble[,10] [14 x 10]> <lm> 

【讨论】:

  • 因子声明是重现问题条件所必需的(见编辑)
  • 我没有意识到您故意使用factor 来创建错误。也许这应该在原始帖子中进行解释。
猜你喜欢
  • 2020-01-27
  • 2022-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多