sql - dbplyr、dplyr 和没有 SQL 等效项的函数 [例如 `slice()`]

标签 sql r dplyr r-dbi dbplyr

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(这不是我的首选解决方案)?

最佳答案

我理解了这个问题:我如何制作 slice()为 SQL 数据库工作?这与“强制使用”不同,但仍然适用于您的情况。

下面的示例显示了如何实现 slice() 的“穷人”变体。这适用于数据库。我们仍然需要做一些跑腿的工作,并用在数据库上工作的动词来实现它,但是我们可以像使用数据框一样使用它。

http://adv-r.had.co.nz/OO-essentials.html#s3 中阅读有关 S3 类的更多信息.

library(tidyverse)
con <- DBI::dbConnect(RSQLite::SQLite(), ":memory:")
copy_to(con, mtcars)
mtcars2 <- tbl(con, "mtcars")

# mtcars2 has a class attribute
class(mtcars2)
#> [1] "tbl_SQLiteConnection" "tbl_dbi"              "tbl_sql"             
#> [4] "tbl_lazy"             "tbl"

# slice() is an S3 method
slice
#> function(.data, ..., .preserve = FALSE) {
#>   UseMethod("slice")
#> }
#> <bytecode: 0x560a03460548>
#> <environment: namespace:dplyr>

# we can implement a "poor man's" variant of slice()
# for the particular class. (It doesn't work quite the same
# in all cases.)
#' @export
slice.tbl_sql <- function(.data, ...) {
  rows <- c(...)

  .data %>%
    mutate(...row_id = row_number()) %>%
    filter(...row_id %in% !!rows) %>%
    select(-...row_id)
}

mtcars2 %>%
  slice(1:5)
#> # Source:   lazy query [?? x 11]
#> # Database: sqlite 3.29.0 [:memory:]
#>     mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#>   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1  21       6   160   110  3.9   2.62  16.5     0     1     4     4
#> 2  21       6   160   110  3.9   2.88  17.0     0     1     4     4
#> 3  22.8     4   108    93  3.85  2.32  18.6     1     1     4     1
#> 4  21.4     6   258   110  3.08  3.22  19.4     1     0     3     1
#> 5  18.7     8   360   175  3.15  3.44  17.0     0     0     3     2

创建于 2019-12-07 由 reprex package (v0.3.0)

关于sql - dbplyr、dplyr 和没有 SQL 等效项的函数 [例如 `slice()`],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59217666/

相关文章:

javascript - 如何保存函数的输入值?

SQL Server 2016,无效的对象名称 'STRING_SPLIT'

mysql - 将两个单独的 SQL 查询合并为一个

r - 如何在 R 中读取一行一行的 CSV?

r - 将分组模型重新应用到数据上

mysql - 复杂派生表的 SUM

R中的递归迷宫求解器

r - igraph 中的二度连接

r - 如何移动嵌套 tibbles 中的 tibbles 列?

r - 在嵌套数据框的列上实现 map()