【问题标题】:Why I cannot apply a function to a list of lm fit using map?为什么我不能使用 map 将函数应用于 lm fit 列表?
【发布时间】:2020-09-24 05:36:04
【问题描述】:

我正在使用嵌套数据框和map 函数将线性回归模型拟合到不同的组。之后,我想对lm 的每个拟合进行分段回归。

在此示例中,diamonds2 包含一个列 Fit_lm,其中 lm 适合每个组。之后,我想我可以再次使用map 来应用segmented 函数,但是代码不起作用(参见diamonds3)。

不过,如果我将 lmsegmented 组合在同一个函数中,代码就可以工作(请参阅 diamonds4)。

如果可能的话,我想了解mapsegmented 不能在lm 对象上工作的原因?这是否与map 函数的工作方式有关?当然,我可以像diamonds4那样做同样的事情,但是由于我已经适合lm一次,所以这个策略效率不高。

library(tidyverse)
library(segmented)

data("diamonds")

diamonds2 <- diamonds %>%
  group_by(cut) %>%
  nest() %>%
  mutate(Fit_lm = map(data, ~lm(price ~ carat, data = .x))) 

diamonds3 <- diamonds2 %>%
  # segmented regression
  mutate(Fit_seg = map(Fit_lm, ~segmented(.x, seg.Z = ~carat)))
# Error: Problem with `mutate()` input `Fit_seg`.
# x cannot coerce class ‘"lm"’ to a data.frame
# i Input `Fit_seg` is `map(Fit_lm, ~segmented(.x, seg.Z = ~carat))`.
# i The error occured in group 1: cut = "Fair".
# Run `rlang::last_error()` to see where the error occurred.

diamonds4 <- diamonds2 %>%
  #  lm and segmented regression
  mutate(Fit_seg = map(data, function(x){
    fit <- lm(price ~ carat, data = x)
    fit2 <- segmented(fit, seg.Z = ~carat)
    return(fit2)
  }))

【问题讨论】:

  • 这不是map 的事情; lapply 也会发生同样的事情。通过调试器运行它,它看起来像是segmented.lm 中如何处理环境的产物; mf &lt;- eval(mf, parent.frame()) 行是错误的。
  • @alistaire 感谢您对此进行检查。我想你是对的。这与环境的处理方式有关。

标签: r list tidyverse purrr lm


【解决方案1】:

您可以使用新的 dplyr 1.0.0

library(tidyverse)
library(segmented)

data("diamonds")

diamonds2 <- diamonds %>%
  nest_by(cut) %>% 
  mutate(fit_lm = list(lm(price ~ carat,data = data)),
         seg = list(segmented(fit_lm,seg.Z = ~carat)))

diamonds2
#> # A tibble: 5 x 4
#> # Rowwise:  cut
#>   cut                     data fit_lm seg       
#>   <ord>     <list<tbl_df[,9]>> <list> <list>    
#> 1 Fair             [1,610 x 9] <lm>   <segmentd>
#> 2 Good             [4,906 x 9] <lm>   <segmentd>
#> 3 Very Good       [12,082 x 9] <lm>   <segmentd>
#> 4 Premium         [13,791 x 9] <lm>   <segmentd>
#> 5 Ideal           [21,551 x 9] <lm>   <segmentd>

reprex package (v0.3.0) 于 2020-06-05 创建

devtools::session_info()
#> - Session info ---------------------------------------------------------------
#>  setting  value                       
#>  version  R version 4.0.0 (2020-04-24)
#>  os       Windows 10 x64              
#>  system   x86_64, mingw32             
#>  ui       RTerm                       
#>  language (EN)                        
#>  collate  English_United Kingdom.1252 
#>  ctype    English_United Kingdom.1252 
#>  tz       America/Sao_Paulo           
#>  date     2020-06-05                  
#> 
#> - Packages -------------------------------------------------------------------
#>  package     * version    date       lib source                              
#>  assertthat    0.2.1      2019-03-21 [1] CRAN (R 4.0.0)                      
#>  backports     1.1.7      2020-05-13 [1] CRAN (R 4.0.0)                      
#>  blob          1.2.1      2020-01-20 [1] CRAN (R 4.0.0)                      
#>  broom         0.5.6      2020-04-20 [1] CRAN (R 4.0.0)                      
#>  callr         3.4.3      2020-03-28 [1] CRAN (R 4.0.0)                      
#>  cellranger    1.1.0      2016-07-27 [1] CRAN (R 4.0.0)                      
#>  cli           2.0.2      2020-02-28 [1] CRAN (R 4.0.0)                      
#>  colorspace    1.4-1      2019-03-18 [1] CRAN (R 4.0.0)                      
#>  crayon        1.3.4      2017-09-16 [1] CRAN (R 4.0.0)                      
#>  DBI           1.1.0      2019-12-15 [1] CRAN (R 4.0.0)                      
#>  dbplyr        1.4.4      2020-05-27 [1] CRAN (R 4.0.0)                      
#>  desc          1.2.0      2018-05-01 [1] CRAN (R 4.0.0)                      
#>  devtools      2.3.0      2020-04-10 [1] CRAN (R 4.0.0)                      
#>  digest        0.6.25     2020-02-23 [1] CRAN (R 4.0.0)                      
#>  dplyr       * 1.0.0      2020-05-29 [1] CRAN (R 4.0.0)                      
#>  ellipsis      0.3.1      2020-05-15 [1] CRAN (R 4.0.0)                      
#>  evaluate      0.14       2019-05-28 [1] CRAN (R 4.0.0)                      
#>  fansi         0.4.1      2020-01-08 [1] CRAN (R 4.0.0)                      
#>  forcats     * 0.5.0      2020-03-01 [1] CRAN (R 4.0.0)                      
#>  fs            1.4.1      2020-04-04 [1] CRAN (R 4.0.0)                      
#>  generics      0.0.2      2018-11-29 [1] CRAN (R 4.0.0)                      
#>  ggplot2     * 3.3.1      2020-05-28 [1] CRAN (R 4.0.0)                      
#>  glue          1.4.1      2020-05-13 [1] CRAN (R 4.0.0)                      
#>  gtable        0.3.0      2019-03-25 [1] CRAN (R 4.0.0)                      
#>  haven         2.3.0      2020-05-24 [1] CRAN (R 4.0.0)                      
#>  highr         0.8        2019-03-20 [1] CRAN (R 4.0.0)                      
#>  hms           0.5.3      2020-01-08 [1] CRAN (R 4.0.0)                      
#>  htmltools     0.4.0      2019-10-04 [1] CRAN (R 4.0.0)                      
#>  httr          1.4.1      2019-08-05 [1] CRAN (R 4.0.0)                      
#>  jsonlite      1.6.1      2020-02-02 [1] CRAN (R 4.0.0)                      
#>  knitr         1.28       2020-02-06 [1] CRAN (R 4.0.0)                      
#>  lattice       0.20-41    2020-04-02 [2] CRAN (R 4.0.0)                      
#>  lifecycle     0.2.0      2020-03-06 [1] CRAN (R 4.0.0)                      
#>  lubridate     1.7.8      2020-04-06 [1] CRAN (R 4.0.0)                      
#>  magrittr      1.5        2014-11-22 [1] CRAN (R 4.0.0)                      
#>  memoise       1.1.0      2017-04-21 [1] CRAN (R 4.0.0)                      
#>  modelr        0.1.8      2020-05-19 [1] CRAN (R 4.0.0)                      
#>  munsell       0.5.0      2018-06-12 [1] CRAN (R 4.0.0)                      
#>  nlme          3.1-147    2020-04-13 [2] CRAN (R 4.0.0)                      
#>  pillar        1.4.4      2020-05-05 [1] CRAN (R 4.0.0)                      
#>  pkgbuild      1.0.8      2020-05-07 [1] CRAN (R 4.0.0)                      
#>  pkgconfig     2.0.3      2019-09-22 [1] CRAN (R 4.0.0)                      
#>  pkgload       1.1.0      2020-05-29 [1] CRAN (R 4.0.0)                      
#>  prettyunits   1.1.1      2020-01-24 [1] CRAN (R 4.0.0)                      
#>  processx      3.4.2      2020-02-09 [1] CRAN (R 4.0.0)                      
#>  ps            1.3.3      2020-05-08 [1] CRAN (R 4.0.0)                      
#>  purrr       * 0.3.4      2020-04-17 [1] CRAN (R 4.0.0)                      
#>  R6            2.4.1      2019-11-12 [1] CRAN (R 4.0.0)                      
#>  Rcpp          1.0.4.6    2020-04-09 [1] CRAN (R 4.0.0)                      
#>  readr       * 1.3.1      2018-12-21 [1] CRAN (R 4.0.0)                      
#>  readxl        1.3.1      2019-03-13 [1] CRAN (R 4.0.0)                      
#>  remotes       2.1.1      2020-02-15 [1] CRAN (R 4.0.0)                      
#>  reprex        0.3.0      2019-05-16 [1] CRAN (R 4.0.0)                      
#>  rlang         0.4.6      2020-05-02 [1] CRAN (R 4.0.0)                      
#>  rmarkdown     2.2        2020-05-31 [1] CRAN (R 4.0.0)                      
#>  rprojroot     1.3-2      2018-01-03 [1] CRAN (R 4.0.0)                      
#>  rvest         0.3.5      2019-11-08 [1] CRAN (R 4.0.0)                      
#>  scales        1.1.1      2020-05-11 [1] CRAN (R 4.0.0)                      
#>  segmented   * 1.1-0      2019-12-10 [1] CRAN (R 4.0.0)                      
#>  sessioninfo   1.1.1      2018-11-05 [1] CRAN (R 4.0.0)                      
#>  stringi       1.4.6      2020-02-17 [1] CRAN (R 4.0.0)                      
#>  stringr     * 1.4.0      2019-02-10 [1] CRAN (R 4.0.0)                      
#>  testthat      2.3.2      2020-03-02 [1] CRAN (R 4.0.0)                      
#>  tibble      * 3.0.1      2020-04-20 [1] CRAN (R 4.0.0)                      
#>  tidyr       * 1.1.0      2020-05-20 [1] CRAN (R 4.0.0)                      
#>  tidyselect    1.1.0      2020-05-11 [1] CRAN (R 4.0.0)                      
#>  tidyverse   * 1.3.0.9000 2020-05-16 [1] Github (tidyverse/tidyverse@1d7f9b7)
#>  usethis       1.6.1      2020-04-29 [1] CRAN (R 4.0.0)                      
#>  utf8          1.1.4      2018-05-24 [1] CRAN (R 4.0.0)                      
#>  vctrs         0.3.0      2020-05-11 [1] CRAN (R 4.0.0)                      
#>  withr         2.2.0      2020-04-20 [1] CRAN (R 4.0.0)                      
#>  xfun          0.14       2020-05-20 [1] CRAN (R 4.0.0)                      
#>  xml2          1.3.2      2020-04-23 [1] CRAN (R 4.0.0)                      
#>  yaml          2.2.1      2020-02-01 [1] CRAN (R 4.0.0)                      
#> 
#> [1] C:/Users/brunotc1/Documents/R/win-library/4.0
#> [2] C:/Program Files/R/R-4.0.0/library

【讨论】:

  • 它对我来说很好,但我认为答案应该以diamonds2 开头。 OP 已经发现如果一起完成它可以工作。
  • 是的,我没有回答为什么分段失败,我从来没有使用过这个包,我最好的猜测是范围丢失了克拉变量,操作解决方案需要两个步骤才能保留 lm结果,或答案的一些取消嵌套
  • 感谢您的回答。这是我第一次看到nest_by 是如何工作的。
  • 没问题 dplyr 1.0.0 在 CRAN 上确实是新的,我发现大多数地图问题都可以使用它解决
【解决方案2】:

运行segmented时需要函数中的数据。此外,数据的名称应与您运行 lm 时的名称相同。

所以这行得通:

library(dplyr)
library(purrr)
library(segmented)

diamonds2 %>%
  mutate(Fit_seg = map2(data, Fit_lm, ~segmented(.y, seg.Z = ~carat)))

#  cut       data                  Fit_lm Fit_seg   
#  <ord>     <list>                <list> <list>    
#1 Ideal     <tibble [21,551 × 9]> <lm>   <segmentd>
#2 Premium   <tibble [13,791 × 9]> <lm>   <segmentd>
#3 Good      <tibble [4,906 × 9]>  <lm>   <segmentd>
#4 Very Good <tibble [12,082 × 9]> <lm>   <segmentd>
#5 Fair      <tibble [1,610 × 9]>  <lm>   <segmentd>

但这不会:

diamonds2 %>%
  mutate(Fit_seg = map2(Fit_lm, data, ~segmented(.x, seg.Z = ~carat)))

这是因为当您运行 lm 时,您的数据被命名为 .x

因此即使您使用匿名函数运行它也会失败,因为.xx 不同。

diamonds2 %>% mutate(Fit_seg = map2(data, Fit_lm, 
            function(x, y) segmented(y, seg.Z = ~carat)))

所以我想最好的解决方案是在同一个函数中使用segmentedlm,这样你就可以同时拥有数据和lm 对象。

【讨论】:

  • 感谢您的回答。在您的第一个代码示例中,为什么我们不必在 map2 函数中指定 .x?我查看了segmented函数的文档,并没有指定data的参数,所以我很好奇。
  • segmented 没有 data 参数。数据应该存在于调用它的环境中并且具有相同的名称。我也没有使用过segmented,但是当我运行segmented(diamonds2$Fit_lm[[1]], seg.Z = ~carat) 时我得到了提示,它返回Error in is.data.frame(data) : object '.x' not found
  • 所以map2 可以缺少.x 可以吗?您的第一个代码示例只有.y。这是否会使segmented 函数在环境中查找data
  • .x 并没有丢失。我们选择不在我们调用的函数的任何地方使用它。 segmented 函数默认在环境中查找数据。 .x 的目的是仅在调用 segmented 的环境中可用。
猜你喜欢
  • 2021-05-13
  • 2021-08-24
  • 2017-06-17
  • 2012-06-11
  • 1970-01-01
  • 2013-06-02
  • 2021-02-28
  • 2015-04-16
  • 2022-05-03
相关资源
最近更新 更多