【问题标题】:Accessing results from a list column when some elements are NA当某些元素为 NA 时从列表列访问结果
【发布时间】:2021-07-17 17:37:17
【问题描述】:

问题:列表列包含一些缺失值

数据

考虑以下包含 2 个模型拟合结果的小标题:

> Model_fits
# A tibble: 4 x 4
    cyl               data model1    model2   
  <dbl> <list<tibble[,2]>> <list>    <list>   
1     2            [5 x 2] <dbl [1]> <dbl [1]>
2     4           [11 x 2] <lm>      <lm>     
3     6            [7 x 2] <lm>      <dbl [1]>
4     8           [14 x 2] <lm>      <lm>  

此示例中缺少cyl==2 的数据。因此,model1 在第一行包含NA_real_。同样,model2 在第 1 行和第 3 行中包含 NA_real_

提取模型结果

我想使用broom::glance 提取模型拟合的结果。但由于缺少值,它不起作用:

> Model_fits %>% 
+   mutate(summary_res = map(model1, broom::glance))
Error: Problem with `mutate()` input `summary_res`.
x No glance method for objects of class numeric
i Input `summary_res` is `map(model1, broom::glance)`.

尝试解决方案

所以,我尝试使用purrr::possibly,但这也不起作用:

> Model_fits %>% 
+   mutate(summary_res1 = map(model1, ~ possibly(broom::glance(.x),
+                                              otherwise = NA_real_)))
Error: Problem with `mutate()` input `summary_res1`.
x No glance method for objects of class numeric
i Input `summary_res1` is `map(model1, ~possibly(broom::glance(.x), otherwise = NA_real_))`.

预期结果

我想获得所有非缺失值的broom::glance 结果和所有缺失值的NA_real_。请指导我如何获得这些结果?

创建代码Model_fits

请注意,我创建了以下内容作为可重现的示例。但这不是我的原始数据/模型结果。

library(tidyverse)

new_data <- tibble(mpg = rep(NA_real_, 5),
       cyl = rep(2, 5),
       disp = rep(NA_real_, 5))

mtcars2 <- mtcars %>% 
  dplyr::select(mpg, cyl, disp)

mt <- bind_rows(mtcars2, 
                new_data)
  
model_res_list <- map(mtcars2 %>% group_split(cyl), ~lm(mpg ~ disp, data = .x))

lizt <- list(NA_real_, model_res_list[[1]], model_res_list[[2]], model_res_list[[3]])

lizt2 <- list(NA_real_, model_res_list[[1]], NA_real_, model_res_list[[3]])


Model_fits <- mt %>% 
  group_nest(cyl) %>% 
  mutate(model1 = lizt,
         model2 = lizt2) 

【问题讨论】:

    标签: r try-catch tidyverse purrr


    【解决方案1】:

    您可以对此做的另一件事是使用tryCatch 函数,以便在发生错误时定义函数的输出。在这种情况下,它不会停止函数的执行。

    Model_fits %>%
      mutate(mod01 = map(model1, ~ tryCatch(glance(.x), 
                                            error = function(cond) {
                                              NA_real_
                                            }))) %>%
      unnest(mod01)
    
    # A tibble: 4 x 17
        cyl         data model1  model2 mod01 r.squared adj.r.squared sigma statistic  p.value    df
      <dbl> <list<tibbl> <list>  <list> <dbl>     <dbl>         <dbl> <dbl>     <dbl>    <dbl> <dbl>
    1     2      [5 x 2] <dbl [~ <dbl ~    NA   NA             NA     NA      NA      NA          NA
    2     4     [11 x 2] <lm>    <lm>      NA    0.648          0.609  2.82   16.6     0.00278     1
    3     6      [7 x 2] <lm>    <dbl ~    NA    0.0106        -0.187  1.58    0.0537  0.826       1
    4     8     [14 x 2] <lm>    <lm>      NA    0.270          0.209  2.28    4.44    0.0568      1
    # ... with 6 more variables: logLik <dbl>, AIC <dbl>, BIC <dbl>, deviance <dbl>,
    #   df.residual <int>, nobs <int>
    

    如果我们想使用possiblysafely 而不是tryCatch,我们应该首先编写一个自定义函数来包装glance,然后再应用于我们的数据集:

    poss_glance <- possibly(glance, otherwise = NA_real_)
    
    Model_fits %>%
      mutate(mod01 = map(model1, ~ poss_glance(.x))) %>%
      unnest(mod01)
    
    # A tibble: 4 x 17
        cyl         data model1  model2 mod01 r.squared adj.r.squared sigma statistic  p.value    df
      <dbl> <list<tibbl> <list>  <list> <dbl>     <dbl>         <dbl> <dbl>     <dbl>    <dbl> <dbl>
    1     2      [5 x 2] <dbl [~ <dbl ~    NA   NA             NA     NA      NA      NA          NA
    2     4     [11 x 2] <lm>    <lm>      NA    0.648          0.609  2.82   16.6     0.00278     1
    3     6      [7 x 2] <lm>    <dbl ~    NA    0.0106        -0.187  1.58    0.0537  0.826       1
    4     8     [14 x 2] <lm>    <lm>      NA    0.270          0.209  2.28    4.44    0.0568      1
    # ... with 6 more variables: logLik <dbl>, AIC <dbl>, BIC <dbl>, deviance <dbl>,
    #   df.residual <int>, nobs <int>
    

    或者我们甚至可以使用safely 代替possibly,以便我们的函数在这种情况下返回增强的输出NA_real_

    safe_glance <- safely(glance, otherwise = NA_real_)
    
    Model_fits %>%
      mutate(mod01 = map(model1, ~ safe_glance(.x)))
    

    【讨论】:

    • 谢谢。 purrr::possibly()tryCatch() 相似,但语法更简单。但这对我不起作用。
    • 非常感谢。我现在明白这个问题了。选择此作为解决方案是因为在模型对象上执行 is.na() 会引发警告。
    • 很高兴它有帮助,我自己刚刚了解到它。我建议您也阅读文档,在这种情况下它非常有帮助,因为我意识到它在应用数据时从不包装函数,而是在应用之前编写一个自定义来包装函数。关于答案的选择,这取决于你,我不介意被选中/不被选中。这是一个非常好的问题。赞成。
    【解决方案2】:

    您可以在传递给map 的包装函数中检查值是否为NA

    Model_fits %>% 
       mutate(summary_res = map(model1, function(x) if (length(x) == 1 && is.na(x)) NA_real_ else  broom::glance(x)))
    

    【讨论】:

    • 谢谢!我想知道为什么possibly() 不起作用。
    猜你喜欢
    • 2021-08-23
    • 2018-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-05
    • 2015-02-10
    • 2012-01-14
    • 1970-01-01
    相关资源
    最近更新 更多