【问题标题】:Error using 'segmented' with lm extracted from output of tidyverse 'map' in R使用从 R 中的 tidyverse 'map' 的输出中提取的 lm 使用 'segmented' 时出错
【发布时间】:2019-10-23 14:51:28
【问题描述】:

我正在使用“分段”包来查找 R 中线性回归中的断点

library(tidyverse)
library(segmented)

df <- data.frame(x = c(1:10), y = c(1,1,1,1,1,6:10))
lm_model <- lm(y ~ x, data = df)
seg_model <- segmented(obj = lm_model, seg.Z = ~ x)

但如果我在 purrr:map 中运行相同的模型,分段会失败。

map_test <- df %>% 
  nest() %>%
  mutate(map_lm = map(data, ~lm(y ~ x, data = .)),
         param_map_lm = map(map_lm, tidy))

map_lm_model <- map_test[[2]][[1]]

map_seg_model <- segmented(obj = map_lm_model, seg.Z = ~ x)

“is.data.frame(data) 中的错误:对象 '.'没找到”

当从map输出中提取的lm中取出lm obj时,segmented找不到底层数据。

然而,这两个线性模型对象看起来是相同的。

我真正需要做的是一个更有用的地图,在数据帧的多个子集上运行 lm,然后在生成的 lm 上“分段”运行。

【问题讨论】:

    标签: r purrr


    【解决方案1】:

    这和the interaction between glm() and purrr::map()基本是同一个问题。

    lm() 捕获提供给它的表达式,这在独立的情况下工作得很好。但是,当被map() 调用时,提供的表达式是.,它在map() 调用的直接上下文之外没有任何意义,并导致您观察到的错误。

    与另一个问题一样,一种解决方法是为lm() 定义一个包装器,该包装器直接在数据集上构成自定义调用,然后lm() 将其捕获为未计算的表达式。

    # Composes a custom lm() expression and evaluates it
    lm2 <- function(data, ...)
        eval( rlang::expr(lm(data=!!rlang::enexpr(data), !!!list(...))) )
    
    # Now mapping using lm2, instead of lm
    map_test <- nest(df, data=everything()) %>% 
        mutate(map_lm       = map(data, lm2, y ~ x),
               param_map_lm = map(map_lm, broom::tidy))
    
    # The data is stored directly inside the lm object
    # segmented() now has no problems accessing it
    map_lm_model <- map_test[[2]][[1]]
    map_seg_model <- segmented(obj = map_lm_model, seg.Z = ~ x)
    # Call: segmented.lm(obj = map_lm_model, seg.Z = ~x)
    # 
    # Meaningful coefficients of the linear terms:
    # (Intercept)            x         U1.x  
    #   1.000e+00    6.344e-15    1.607e+00  
    # 
    # Estimated Break-Point(s):
    # psi1.x  
    #  3.889  
    

    或作为单个mutate() 链:

    map_test <- nest(df, data=everything()) %>% 
        mutate(map_lm       = map(data, lm2, y ~ x),
               param_map_lm = map(map_lm, broom::tidy),
               seg_lm       = map(map_lm, segmented, seg.Z=~x))
    # # A tibble: 1 x 4
    #             data map_lm param_map_lm     seg_lm    
    #   <list<df[,2]>> <list> <list>           <list>    
    # 1       [10 × 2] <lm>   <tibble [2 × 5]> <segmentd>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-03
      • 2018-07-13
      • 2017-10-25
      • 2021-08-26
      • 1970-01-01
      • 1970-01-01
      • 2017-10-14
      • 1970-01-01
      相关资源
      最近更新 更多