首页 > 解决方案 > dplyr 对数据框和数据库的工作方式不同 - 如何解决?

问题描述

显然,dplyr 需要对数据框和数据库进行不同的实现。这不是我第一次遇到这种情况。示例代码如下。代码的目的是Inf从数据库中删除值。

library(RSQLite)
library(DBI)

# dataframe
data <- data.frame(x = c(rep(1,2), rep(Inf, 3), rep(1, 5)),
                   y = c(rep(2,5), rep(Inf, 5)),
                   z = 1:10)

# database
db <- DBI::dbConnect(RSQLite::SQLite(), ":memory:")
copy_to(db, data, name = "data", overwrite = TRUE)

data_db <- tbl(db, "data")

# WORKS for dataframe:
data %>% filter_at(c("x", "y"), all_vars(base::is.finite(.)))

# DOES NOT WORK for database
data_db %>% filter_at(c("x", "y"), all_vars(base::is.finite(.)))

最后一行返回错误:

Error in eval_bare(call, env) : object 'x' not found

是否对数据帧与数据库的 dplyr 实现所需的差异有一个很好的概述?

请帮助使上述代码适用于数据库案例。谢谢

标签: rdatabasedataframedplyr

解决方案


翻看dbplyrFunction translation vignette,好像没有is.finite()提到,确实我们可以验证它不知道如何翻译is.infinite为 SQL command ISFINITE()

dbplyr::translate_sql(is.infinite(x))
# <SQL> is.infinite(`x`)

在这种情况下,根据使用 dbplyr小插图编写 SQL,您可以使用如下sql命令:

## write idea, but probably won't work
data_db %>% filter(across(c("x", "y"), sql(NOT ISFINITE(.))))

.尽管不可否认,由于SQL 中的原因,它看起来工作的可能性很小。我不确定across()(或较旧的filter_atdplyr函数与该sql()函数的关系如何。您可能需要写出要过滤的列:

data_db %>% filter(sql(NOT ISFINITE(x)), sql(NOT ISFINITE(y)))

是否对数据帧与数据库的 dplyr 实现所需的差异有一个很好的概述?

上面提到的小插曲都是很好的阅读。


推荐阅读