如何使用 dplyr 包在 R 中使用连接的数据库?
How to work with connected DB in R using dplyr package?
我正在寻找一种使用 R 处理连接的数据库的方法,这样我就不必将数据库上传到我的内存中。我一直在使用 pool
或 DBI
包连接到数据库并使用 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]
对于这个问题我还没有想出任何解决方案,任何关于如何解决它的想法将不胜感激。
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 的来龙去脉,那么最好在考虑切片之前确保排序。
一般来说(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
,所以在这里可能会更好,无论如何。)
factor
的概念在 SQL 中没有通用的等价物,至少在我相信您想要使用它的方式中没有。这是一个R的东西。所以我建议你 mutate
和 filter
你需要什么,当你确信你只需要 rows/columns 时,然后 collect()
你的数据(将所有行检索到 R ), 然后 然后 transmute
变成 factor
.
我正在寻找一种使用 R 处理连接的数据库的方法,这样我就不必将数据库上传到我的内存中。我一直在使用 pool
或 DBI
包连接到数据库并使用 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 字符,我想将其更改为因子。我尝试了以下代码,它在没有连接的数据库的情况下也能正常工作。
my_db %>% tbl("bbb") %>%
transmute (colname = factor(colname))
#Error: FUNCTION aaa.factor does not exist [1305]
对于这个问题我还没有想出任何解决方案,任何关于如何解决它的想法将不胜感激。
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 的来龙去脉,那么最好在考虑切片之前确保排序。
一般来说(
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
,所以在这里可能会更好,无论如何。)factor
的概念在 SQL 中没有通用的等价物,至少在我相信您想要使用它的方式中没有。这是一个R的东西。所以我建议你mutate
和filter
你需要什么,当你确信你只需要 rows/columns 时,然后collect()
你的数据(将所有行检索到 R ), 然后 然后transmute
变成factor
.