R dbplyr 2.1 用if_any类across函数操作远程表报错咨询
报错根因
在本地内存表运行相同if_any()代码可以正常输出结果,连接BigQuery远程表时触发报错不属于语法错误:本地计算走R原生执行逻辑,不经过SQL转译环节,因此不会触发转译问题;你使用的dbplyr 2.1版本在远程表的SQL转译链路中,尚未覆盖两个场景:
- 无法识别
~开头的匿名公式对象,碰到这类对象时找不到对应转译方法,抛出escape方法缺失的报错 - 无法在远程表查询中正确解析
where(is.xxx)这类基于列属性的谓词选列逻辑,碰到传入的函数对象时同样会触发转译失败
适配2.1版本的临时实现方案
以下方案全部依托数据库端完成计算,无需拉取全表到本地执行,不会损失查询性能:
- 列数量少、列名明确的场景,直接显式列出需要检测的列,用布尔逻辑拼接匹配结果适配BigQuery字符串匹配规则
# 实现任意列包含"ab"则标记为TRUE的需求 my_table_bq %>% mutate( has_ab = A %like% "ab" | B %like% "ab" | C %like% "ab" ) - 需对多列重复执行相同检测逻辑的场景,先定义普通命名函数替代
~开头的匿名公式,让转译器可以正常识别逻辑生成对应SQL# 定义可被正常转译的匹配函数 match_ab <- function(col) { grepl("ab", col) } my_table_bq %>% mutate( has_ab = if_any(c(A, B, C), match_ab) ) - 列选择环节不要使用
where(is.xxx)的谓词写法,先通过远程表元数据提取对应属性的列名,显式传入列名向量即可# 提前提取所有数值列的列名,替代where(is.numeric)的写法 numeric_cols <- colnames(my_table_bq)[dbplyr::sql_col_classes(my_table_bq) == "numeric"] my_table_bq %>% mutate(across(all_of(numeric_cols), mean))
后续dbplyr 2.2及以上版本已补全对匿名公式、
where()谓词选列的远程转译支持,升级版本后原有的写法即可直接在BigQuery远程表上运行。
内容的提问来源于stack exchange,提问作者abalter
相关产品推荐
相关产品推荐

