You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在自定义函数的公式中正确使用quosures解引用变量?

我明白你在自定义数据处理函数里用quosures传递变量名到公式时遇到了问题——这在使用tidyeval工具时确实是个常见的小坑!让我帮你把代码修正过来,顺便解释下正确的用法。

解决Quosures在公式中解引用的问题

首先,我猜你原本的函数是想按分组变量拟合模型,再用broom处理结果对吧?你的核心问题是在公式里正确解引用quosures,其实用!!(bang-bang操作符)就可以,但要注意公式里的写法,以及结合purrr::map的正确方式。

修正后的完整函数

library(dplyr)
library(broom)
library(purrr)
library(tidyr)

foo <- function(mydata, dv, iv, group_var) {
  # 捕获输入的变量名作为quosures
  dv <- enquo(dv)
  iv <- enquo(iv)
  group_var <- enquo(group_var)
  
  mydata %>%
    group_by(!!group_var) %>%
    nest() %>%
    # 对每个分组的数据拟合模型,公式里解引用quosures
    mutate(model = map(data, ~ lm(!!dv ~ !!iv, data = .x)),
           # 用broom整理模型的系数结果
           tidied = map(model, tidy),
           # 用broom整理模型的整体统计量
           glanced = map(model, glance)) %>%
    # 展开整理后的系数结果
    unnest(tidied) %>%
    # 提取需要的列,包括分组变量和模型统计量
    select(!!group_var, term, estimate, p.value, r.squared = glanced$r.squared)
}

关键步骤解释

  • 捕获变量:用enquo()把函数的参数转换成quosures,这样我们就能在后续的tidyverse函数里安全地引用这些变量名,避免命名冲突。
  • 公式中的解引用:在lm()的公式里,直接用!!dv ~ !!iv就能把quosures转换成对应的列名,R会正确识别这是数据框里的变量。
  • 结合map使用:在map()里,我们用.x指代每个分组的子集数据集,把解引用后的公式和数据一起传递给lm()即可完成分组建模。

测试示例

用mtcars数据集测试这个函数,看看效果:

test_result <- foo(mtcars, mpg, hp, cyl)
print(test_result)

运行后你会得到按cyl(气缸数)分组,每个组里mpg(油耗)对hp(马力)回归的系数、p值和R平方值。

更简洁的写法(使用{{ }})

如果你用的是dplyr 1.0.0及以上版本,可以用{{ }}(curly-curly操作符)简化代码,它会自动完成quosures的捕获和解引用,不需要手动调用enquo()和!!:

foo_simpler <- function(mydata, dv, iv, group_var) {
  mydata %>%
    group_by({{ group_var }}) %>%
    nest() %>%
    mutate(model = map(data, ~ lm({{ dv }} ~ {{ iv }}, data = .x)),
           tidied = map(model, tidy),
           glanced = map(model, glance)) %>%
    unnest(tidied) %>%
    select({{ group_var }}, term, estimate, p.value, r.squared = glanced$r.squared)
}

这个版本的代码更简洁,功能和之前的完全一致,推荐优先使用这种写法,减少手动处理quosures的麻烦。

内容的提问来源于stack exchange,提问作者Joe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:56:30