【问题标题】:dbplyr window function for grouped mutate operations用于分组变异操作的 dbplyr 窗口函数
【发布时间】:2017-07-11 18:38:07
【问题描述】:

我想使用dbplyr/dplyr 创建一个组级聚合变量。以下是命令的要点:

q = tbl_copy %>% 
  group_by(group_var) %>%
  mutate(x_agg = min(x))

但这会产生以下错误: Error: Window function `min()` is not supported by this database

奇怪的是,当我使用 summarise() 动词时,min() 工作得很好。

q = tbl_copy %>% 
  group_by(group_var) %>%
  summarise(x_agg = min(x))

q %>% show_query()
<SQL>
SELECT `group_var`, `x`, MIN(`x`) AS `x_agg`
FROM `my_table`
GROUP BY `group_var`

我错过了什么?如何在 MySQL 表的副本上使用 group_by()mutate()

更新:一个可重现的例子

> con <- DBI::dbConnect(RSQLite::SQLite(), ":memory:")
> copy_to(con, mtcars)
> 
> mtcars2 <- tbl(con, "mtcars")
> mtcars2 %>%
+     select(mpg,cyl) %>%
+     group_by(cyl) %>%
+     mutate(mpg_min = min(mpg))
Error: Window function `min()` is not supported by this database

【问题讨论】:

    标签: mysql r dplyr dbplyr


    【解决方案1】:

    MySQL 不支持窗口函数,这就是 dbplyr 无法将您的 dplyr 代码转换为 SQL 的原因。

    当您使用 MySQL 数据库时,通常的解决方法是使用嵌套 SQL 查询,例如:

    select yt.*, t.x_agg
    from yourtable yt inner join (select group_var, min(x) as x_agg 
                                  from yt 
                                  group by group_var) t 
                        on yt.group_var = t.group_var
    

    您可以使用dbGetQuery 将上述查询直接发送到 MySQL 或将此策略转换为 dplyr 代码:

    tbl_copy %>% 
      inner_join(tbl_copy %>% 
                   group_by(group_var) %>%
                   summarise(x_agg = min(x)), by = "group_var")
    

    还要注意,如果您的表足够小,更直接的方法是在内存中完成所有操作(我的意思是:在客户端,即在 R 中)。

    【讨论】:

    • 是的,我明白了。期望dplyr 在 SQL 翻译中以编程方式编写这些子查询是不合理的吗?我经常使用 groupwise mutate(),而且我很想避免用一堆 left_join() 语句重写我的 dplyr 代码。这在很大程度上违背了使用dplyr 代替关系数据库的目的。
    • 我同意如果dplyr 能解决这个问题就好了!但我不知道我们是否应该期待它......无论如何,在某些时候你总是需要编写精心优化的 SQL 查询,我认为这不能通过从另一种语言的自动翻译来完成(特别是考虑到事实每个 DBMS 都有自己的 SQL 实现)。
    猜你喜欢
    • 1970-01-01
    • 2012-02-09
    • 2017-05-14
    • 1970-01-01
    • 1970-01-01
    • 2021-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多