如何使用 dplyr 包在 R 中使用连接的数据库?

How to work with connected DB in R using dplyr package?

我正在寻找一种使用 R 处理连接的数据库的方法,这样我就不必将数据库上传到我的内存中。我一直在使用 poolDBI 包连接到数据库并使用 dplyr 进行数据操作,但我发现了一些我无法解决的问题:

加载数据:

library(pool)
library(dplyr)
library(RMariaDB)

my_db <- dbPool(
  MariaDB(),
  donate = "aaa",
  host = "localhost",
  username = "root"
)

- 第一个问题:无法使用切片函数

my_db %>% tbl("bbb") %>%
  slice(2:10)
#Error: slice() is not supported on database backends

对于这个问题,我想出了以下解决方法:

my_db %>% tbl("bbb") %>%
  mutate(Rowindx = row_number()) %>%
  filter(Rowindx >= 2 && Rowindx <= 10) 

这对我有用,但我想知道 这个问题是否有更好的解决方案

- 第二个问题:无法使用 transmute()

更改列的 class 或类型

我有一列 class 字符,我想将其更改为因子。我尝试了以下代码,它在没有连接的数据库的情况下也能正常工作。

my_db %>% tbl("bbb") %>%
  transmute (colname = factor(colname))
#Error: FUNCTION aaa.factor does not exist [1305]

对于这个问题我还没有想出任何解决方案,任何关于如何解决它的想法将不胜感激。

  1. head 有效:

    tbl(con, "mtcars") %>%
      filter(between(disp, 50, 200)) %>%
      head(3) %>%
      show_query()
    # <SQL>
    # SELECT TOP 3 *
    # FROM "mtcars"
    # WHERE ("disp" BETWEEN 50.0 AND 200.0)
    

    (我针对 SQL 服务器进行演示,它使用 SELECT TOP 3 而不是所有其他 DBMS 的 SELECT ... LIMIT 3 标准。)

    当然,这并不能立即执行 2:10 等子集,但如果您只想删除第一行,那么我建议您可以 slice(-1)(在这个例子中)在 collect 将数据完全导入 R 之后(这应该在完成其他过滤以减少下载的数据之后完成)。

    请注意,这是通用切片/head,而不是每组切片,以防您考虑这样做。在 R/dplyr 中,每组通常更喜欢 %>% do(head(10))(returns 每个组的前 10 行)副 %>% head(10)(returns所有数据的前 10 行,无论组)。我还没有发现 do(head(3)) 在 SQL 中工作(尽管我的测试受到限制)。

    附带说明一下,您没有提到对数据进行排序,而且通常无法保证查询中数据的顺序;如果您有特定的订单要求,它应该是特定的。如果您不这样做,则可能无法保证您始终准确获得所需行的概念。当然,我并不是说它是随机的,但存储在 DBMS 中的数据顺序是有意的,由许多因素决定,包括建立在 table 上的索引。如果您不了解所有这些并且了解 DBMS 的来龙去脉,那么最好在考虑切片之前确保排序。

  2. 一般来说(dplyr,不是dbplyr),filter(Rowindx >= 2 && Rowindx <= 10)就是wrong/broken。使用 filter(Rowindx >= 2 & Rowindx <= 10)(单 &,而不是双)或 filter(between(Rowindex, 2, 10))。虽然它在 dbplyr 中仍然有效(&&& 都映射到 SQL 的 AND),但有点 lazy/sloppy当建议使用向量时在 R 中使用它。 (dplyr::between 也映射到 SQL 的 BETWEEN,所以在这里可能会更好,无论如何。)

  3. factor 的概念在 SQL 中没有通用的等价物,至少在我相信您想要使用它的方式中没有。这是一个R的东西。所以我建议你 mutatefilter 你需要什么,当你确信你只需要 rows/columns 时,然后 collect() 你的数据(将所有行检索到 R ), 然后 然后 transmute 变成 factor.