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

为何在R中使用c_across(all_of())执行mutate函数远慢于!!!syms()?

为什么c_across()结合all_of()的行计算写法比!!!syms()慢?

两种写法的性能差异源于底层执行逻辑的本质不同:

  • !!!syms(A)的高效逻辑:
    syms(A)将字符串列名转换为dplyr可识别的符号对象,!!!(非拼接操作符)直接把这些符号展开成列的直接引用。在rowwise()环境中,sum实际是基于列向量做批量计算后再按行聚合,没有额外的对象转换步骤,充分利用了R的向量化计算优势,内存开销极低。

  • c_across(all_of(A))的性能瓶颈:
    c_across()的设计定位是在rowwise()上下文里为每一行单独生成临时向量——它会逐行提取指定列的数值,组装成一个小型向量,再对这个向量执行sum。这种逐行操作带来了三重额外开销:

    1. 为每一行创建独立的小向量,产生大量临时对象
    2. 频繁的对象创建与回收会消耗更多内存资源
    3. sum只能针对单个小向量执行,无法利用向量化计算的效率优势,等同于逐行循环处理

性能验证示例

用microbenchmark可以直观看到差异:

library(microbenchmark)
library(tidyverse)

# 生成1万行的测试数据
df <- data.frame(x = rnorm(10000), y = rnorm(10000))
A <- c("x", "y")

# 基准测试
bench <- microbenchmark(
  syms写法 = df %>% rowwise() %>% mutate(M = sum(!!!syms(A))),
  c_across写法 = df %>% rowwise() %>% mutate(M = sum(c_across(all_of(A)))),
  times = 10
)

print(bench)

测试结果会显示c_across写法的耗时是syms写法的数倍甚至十几倍,数据量越大,这个差距越明显。

适用场景提示

c_across()并非设计用于简单的行求和/均值操作,它更适合需要对行内多列做复杂自定义逐行处理(比如行内条件过滤、自定义函数计算)的场景。如果只是简单的行聚合操作,除了!!!syms()写法,还可以用更高效的非rowwise()写法:

df %>% mutate(M = rowSums(.[A]))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 17:00:21