在R中使用Arrow的dplyr语法对变量指定列求和的正确方法
问题:R中使用Arrow对变量指定列执行递归求和的正确方式
在处理超大数据量(无法载入内存,如Hive分区Parquet文件,通过open_dataset()访问)时,需用Arrow的R接口对变量指定的列执行求和操作,但常规dplyr语法不被Arrow支持,构造临时表达式可行但直接嵌套失败,询问正确/最佳实现方式。
复现代码
初始化数据
library(arrow) library(dplyr) example_data = InMemoryDataset$create(data.frame(a1 = c(1,2,3), b2=c(4,5,6), c3=c(7,8,9))) cols_to_sum = c('a1','b2','c3')
可行的显式列名求和
example_data %>% mutate(computed_sum = a1+b2+c3) %>% compute() # 执行成功
不被Arrow支持的常规dplyr语法
example_data %>% mutate(computed_sum = rowSums(across(all_of(cols_to_sum)))) %>% compute() # 错误提示:Expression rowSums(across(all_of(cols_to_sum))) not supported in Arrow # Call collect() first to pull data into R.
构造临时表达式可行但直接嵌套失败
# 可行写法 temp_expression = parse( text=paste(cols_to_sum, collapse = '+') ) example_data %>% mutate(computed_sum = eval(temp_expression) ) %>% compute() # 执行成功
# 失败写法 example_data %>% mutate(computed_sum = eval( parse( text=paste(cols_to_sum, collapse = '+') ) ) ) %>% compute() # 错误提示:Expression eval(parse(text = paste(cols_to_sum, collapse = "+"))) not supported in Arrow # Call collect() first to pull data into R.
解决方案
不需要依赖eval()和parse(),可以用Arrow支持的reduce()函数结合+运算符实现列的递归求和,这种方式更符合dplyr/Arrow的语法规范,也更易读:
library(purrr) example_data %>% mutate(computed_sum = reduce(across(all_of(cols_to_sum)), `+`)) %>% compute()
原理说明
across(all_of(cols_to_sum))选中目标列,返回包含这些列的Arrow表达式集合purrr::reduce()对集合递归执行+运算,逻辑和显式写a1+b2+c3完全一致- 整个表达式会被Arrow正确解析并在引擎中执行,无需把数据拉到R内存中
如果需要处理含缺失值的情况,可结合coalesce()忽略NA:
example_data %>% mutate(computed_sum = reduce(across(all_of(cols_to_sum)), ~ coalesce(.x, 0) + coalesce(.y, 0))) %>% compute()
关于eval(parse(...))的差异原因
当传入eval(temp_expression)时,temp_expression是已解析好的加法表达式(如a1 + b2 + c3),Arrow能识别这种简单运算;但直接嵌套eval(parse(...))时,整个表达式会被Arrow当作R环境的函数组合调用,而Arrow引擎无法解析这类函数,因此报错。
内容的提问来源于stack exchange,提问作者Maciek
相关产品推荐
相关产品推荐

