dtplyr与dplyr多列分组差异:lapply循环中across报错问题
解决dtplyr在lapply循环中group_by across引用变量报错的问题
问题场景
在dplyr中可正常通过lapply循环对变量组合执行分组筛选:
library(dplyr) mycolumns= c("Wind", "Month", "Ozone", "Solar.R") columnpairs <- as.data.frame(combn(mycolumns, 2)) result_dplyr <- lapply(columnpairs, function(x) { airquality %>% select(all_of(x)) %>% group_by(across(all_of(x))) %>% filter(n() > 1) } )
但切换到dtplyr的lazy_dt后,相同语法会抛出Error in all_of():! object 'x' not found错误:
library(dtplyr) airq <- lazy_dt(airquality) lapply(columnpairs, function(x) { airq %>% select(all_of(x)) %>% group_by(across(all_of(x))) %>% filter(n() > 1) })
解决思路
方法1:使用rlang符号拼接替代across
利用rlang包的syms()将字符向量转换为符号,再通过!!!拼接传入group_by,绕过dtplyr的非标准评估(NSE)环境问题:
library(dtplyr) library(rlang) airq <- lazy_dt(airquality) result_dtplyr <- lapply(columnpairs, function(x) { airq %>% select(all_of(x)) %>% group_by(!!!syms(x)) %>% filter(n() > 1) %>% as_tibble() # 按需转换为普通数据框 })
方法2:临时转换为普通数据框
如果不需要保留lazy_dt的懒加载特性,可以在循环内先将lazy_dt转为tibble,沿用dplyr的原有语法:
library(dtplyr) airq <- lazy_dt(airquality) result_dtplyr <- lapply(columnpairs, function(x) { airq %>% as_tibble() %>% select(all_of(x)) %>% group_by(across(all_of(x))) %>% filter(n() > 1) })
方法3:直接使用data.table原生语法
既然dtplyr底层依赖data.table,直接使用data.table的分组语法更稳定高效:
library(data.table) airq_dt <- as.data.table(airquality) result_dt <- lapply(columnpairs, function(x) { airq_dt[, .SD[.N > 1], by = x] })
报错原因
dtplyr在处理非标准评估(NSE)时与dplyr存在实现差异,across()在lazy_dt的group_by()中无法正确捕获循环变量x的执行环境,导致变量找不到。上述方法通过调整语法或切换底层实现,规避了这个环境绑定问题。
内容的提问来源于stack exchange,提问作者gaut
相关产品推荐
相关产品推荐

