从R中的tidyverse'map'的输出中提取的lm使用'segmented'时出错

时间:2019-10-23 14:51:28

标签: r purrr

我正在使用“分段”包在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)中的错误:对象'。'找不到”

从从地图输出中提取的lm中获取lm obj时,分段无法找到基础数据。

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

我实际上需要做的是一个更有用的映射,以在数据帧的多个子集上运行lm,然后在生成的lm上运行“分段”。

1 个答案:

答案 0 :(得分:0)

这基本上与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>