从 R 中 tidyverse 'map' 的输出中提取的 lm 使用 'segmented' 时出错 [英] Error using 'segmented' with lm extracted from output of tidyverse 'map' in R

查看:46
本文介绍了从 R 中 tidyverse 'map' 的输出中提取的 lm 使用 'segmented' 时出错的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用分段"包在 R 中的线性回归中找到断点

I am using the 'segmented' package to find break points in linear regressions in 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 中运行相同的模型,则分段失败.

But if I run the same model within a purrr:map, segmented fails.

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) 中的错误:对象 '.'未找到"

"Error in is.data.frame(data) : object '.' not found"

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

When taking the lm obj from the lm extracted from the map output, segmented fails to find the underlying data.

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

The two linear model objects, appear, however, identical.

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

What I actually need to do is a more useful map to run lm over multiple sub-sets of a dataframe, then run 'segmented' on the resulting lm.

推荐答案

这与 glm() 和 purrr::map() 之间的交互.

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

lm() captures the expression supplied to it, which works well as a stand-alone case. However, when called by map(), the supplied expression is ., which has no meaning outside the immediate context of that map() call and results in the error you are observing.

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

As with the other question, one workaround is to define a wrapper for lm() that composes a custom call directly on the dataset, which is then captured by lm() as an unevaluated expression.

# 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>

这篇关于从 R 中 tidyverse 'map' 的输出中提取的 lm 使用 'segmented' 时出错的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆