【发布时间】:2020-03-31 17:08:24
【问题描述】:
library(tidyverse)
con <- DBI::dbConnect(RSQLite::SQLite(), ":memory:")
copy_to(con, mtcars)
mtcars2 <- tbl(con, "mtcars")
我可以在上面创建这个模拟 SQL 数据库。我可以在这个“数据库”上执行标准的 dplyr 函数,这非常酷:
mtcars2 %>%
group_by(cyl) %>%
summarise(mpg = mean(mpg, na.rm = TRUE)) %>%
arrange(desc(mpg))
#> # Source: lazy query [?? x 2]
#> # Database: sqlite 3.29.0 [:memory:]
#> # Ordered by: desc(mpg)
#> cyl mpg
#> <dbl> <dbl>
#> 1 4 26.7
#> 2 6 19.7
#> 3 8 15.1
看来我无法使用没有直接 SQL 等效项的 dplyr 函数(例如 dplyr::slice())。对于slice(),我可以使用filter() 和row_number() 的替代组合来获得与仅使用slice() 相同的结果。但是如果没有这么简单的解决方法会发生什么?
mtcars2 %>% slice(1:5)
#>Error in UseMethod("slice_") :
#> no applicable method for 'slice_' applied to an object of class
#> "c('tbl_SQLiteConnection', 'tbl_dbi', 'tbl_sql', 'tbl_lazy', 'tbl')"
当 dplyr 函数没有直接的 SQL 等效项时,我可以强制它们与 dbplyr 一起使用,或者是唯一的选择来使用具有 SQL 等效项的 dplyr 动词来获得创意,或者直接编写 SQL(这不是 my 首选解决方案)?
【问题讨论】:
-
我不知道这是否是首选,但您可以将更大的数据帧拉入内存,然后在 r 对象而不是 sql 表上使用没有等效项的
dplyr动词吗? -
您只需要在
slice(或其他不可翻译的乐趣)之前添加一个collect() %>%行,以便首先将其带入内存,如果您想这样做的话 -
我认为我的建议会是类似的:
mt4 <- RSQLite::dbReadTable(conn = con, "mtcars") %>% slice(1:5)。如果内存是一个问题,我会考虑采用混合方法,在 SQL 中选择和过滤行,然后使用collect拉入较小的子集 -
除了 for slice 之外还有什么功能会导致您出现问题?
-
知道了。如果您尝试获取数据的
View,这对我有用:View(mtcars2 %>% do(head(.,5)))