我正在使用“分段”包在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上运行“分段”。
答案 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>