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

运行Hadley的dplyr NSE编程示例输出异常,求原因解析

dplyr非标准计算(NSE)示例运行不一致/报错的原因解析

问题背景

学习dplyr的非标准计算(NSE)时,参考旧版教程的示例运行结果与预期不符或报错,具体情况如下:

示例1:!!/UQ优先级问题

教程中的示例及预期输出:

my_fun <- quo(fun)
quo(!!my_fun(x, y, z))
#> Error in (function (x) : could not find function "my_fun"
quo(UQ(my_fun)(x, y, z))
#> ~(~fun)(x, y, z)

实际运行输出:

my_fun <- quo(fun)
quo(!!my_fun(x, y, z))
# Error in my_fun(x, y, z) : could not find function "my_fun"
quo(UQ(my_fun)(x, y, z))
# <quosure>
# expr: ^`~`(fun)(x, y, z)
# env:  global

示例2:!!!非引号拼接报错

教程中的示例及预期输出:

args <- list(mean = ~mean(cyl), count = ~n())
mtcars %>%
  group_by(am) %>%
  summarise(!!! args)
#> # A tibble: 2 × 3
#>      am     mean count
#>   <dbl>    <dbl> <int>
#> 1     0 6.947368    19
#> 2     1 5.076923    13

实际运行报错:

Error in `summarise()`:
ℹ In argument: `mean = ~mean(cyl)`.
ℹ In group 1: `am = 0`.
Caused by error:
! `mean` must be a vector, not a <formula> object.
Run `rlang::last_trace()` to see where the error occurred.

改用quo替代公式语法后可正常运行:

args <- list(mean = quo(mean(cyl)), count = quo(n()))
mtcars %>%
  group_by(am) %>%
  summarise(!!! args)
#> # A tibble: 2 × 3
#>      am     mean count
#>   <dbl>    <dbl> <int>
#> 1     0 6.947368    19
#> 2     1 5.076923    13

会话信息:

R version 4.3.3 (2024-02-29 ucrt)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows Server 2019 x64 (build 19045)

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] dplyr_1.1.4

原因解析

核心原因:dplyr版本迭代导致NSE实现变更

你参考的教程基于旧版dplyr(0.7.x及更早版本),而当前使用的是dplyr 1.1.4(1.0+新版),两者在非标准计算的处理逻辑上有显著差异:

  1. 示例1:quosure输出格式变化

    • 旧版中quo()的输出以~开头表示表达式,新版则使用<quosure>结构化输出,明确标注expr(表达式)和env(环境),这是dplyr依赖的rlang包输出格式更新,本质表达式逻辑一致(~fun(x,y,z)和^~(fun)(x,y,z)等价),仅显示形式不同。
    • 报错信息的差异是版本更新后的提示优化,核心错误原因一致:!!优先级问题导致!!my_fun(x,y,z)被解析为!!(my_fun(x,y,z))而非(!!my_fun)(x,y,z),my_fun不是函数因此报错。
  2. 示例2:公式对象不再支持直接传入summarise()

    • 旧版dplyr允许将公式(~)作为参数传入summarise()等函数,内部会自动解析公式右侧的表达式;但新版dplyr(1.0+)严格要求传入参数为可计算的表达式或向量,不再自动处理公式对象,因此直接传入~mean(cyl)会报错。
    • 使用quo()包装表达式后,!!!可正确拼接quosure对象,这是新版dplyr推荐的非标准计算写法,符合当前rlang的整洁评估规范。

补充说明

新版dplyr(1.0+)已逐渐转向使用{{ }}、across()等更简洁的整洁评估接口替代旧版!!/!!!写法,建议优先学习当前版本的官方文档,避免版本差异导致的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 10:13:13