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

use*_*522 8 r purrr

我正在使用 ' segmented' 包来查找 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)
Run Code Online (Sandbox Code Playgroud)

但是,如果我在 a 中运行相同的模型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)
Run Code Online (Sandbox Code Playgroud)

“is.data.frame(data) 中出现错误:对象‘.’ 未找到”

当从映射输出中提取的 lm 中获取 lm obj 时,segmented 无法找到底层数据。

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

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

Art*_*lov 4

这与 glm() 和 purrr::map() 之间的交互基本上是相同的问题。

\n\n

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

\n\n

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

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

或作为单mutate()链:

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