r - 编写自定义 R 函数以在 dbplyr SQL 中使用

标签 r dbplyr

我对任何与 SQL 相关的事情都很陌生,但我觉得我想做的事情一定是可能的。我查看了相关问题,但他们似乎并没有尝试做与我完全相同的事情。

我想编写一个在 dbplyr 管道中使用的函数,因此如果以后再次需要它,我不必重复代码。

我意识到并非 R 中的所有函数都能很好地转换为 SQL,但在本例中,case_when() 可以。当我使用裸代码时它工作得很好,但我不知道如何将它包装在函数中。我编写的函数直接传递到 SQL 中,显然它不是 SQL 中存在的函数。

是否可以让 dbplyr 查看我的函数内的代码,并将其转换为 SQL?

library(pacman)
p_load(dplyr, dbplyr, RSQLite)

# Set up fake database
con <- DBI::dbConnect(RSQLite::SQLite(), dbname = ":memory:")
test = tibble(a = c("a", "b", "c"))
test
#> # A tibble: 3 x 1
#>   a    
#>   <chr>
#> 1 a    
#> 2 b    
#> 3 c
copy_to(con, test)
test_db <- tbl(con, "test")

test_db 上显式使用 case_when() 效果很好。

test_db %>% 
    mutate(b = case_when(
        a == "a" ~ "AAA",
        TRUE ~ a
    ))
#> # Source:   lazy query [?? x 2]
#> # Database: sqlite 3.30.1 [:memory:]
#>   a     b    
#>   <chr> <chr>
#> 1 a     AAA  
#> 2 b     b    
#> 3 c     c

然后我将 case_when() 放入一个函数中,这样我就可以重用它。直接在 test 上运行时效果很好。

func_aaa <- function(x) {
    case_when(
        x == "a" ~ "AAA",
        TRUE ~ x
    )
}

# The function works fine on the regular dataframe
test %>% 
    mutate(b = func_aaa(a))
#> # A tibble: 3 x 2
#>   a     b    
#>   <chr> <chr>
#> 1 a     AAA  
#> 2 b     b    
#> 3 c     c

但它不适用于 test_db。查看它生成的查询,很明显 dbplyr 只是将我的函数名称直接传递到 SQL 中。

test_db %>% 
    mutate(b = func_aaa(a))
#> Error: no such function: func_aaa

test_db %>% 
    mutate(b = func_aaa(a)) %>% 
    show_query()
#> <SQL>
#> SELECT `a`, func_aaa(`a`) AS `b`
#> FROM `test`

reprex package于2020年5月13日创建(v0.3.0)

最佳答案

可能有更简单的方法,但一种选择是使用一个操作并返回整个数据帧的函数,而不是在 mutate 中运行该函数:

func_aaa2 = function(data, var, newvar, val, newval) {
  data %>% 
    mutate({{newvar}} := case_when(
      {{var}} == val ~ newval,
      TRUE ~ {{var}}))
}

test_db %>% 
  func_aaa2(a, "b", "a", "aaa")
  a     b    
  <chr> <chr>
1 a     aaa  
2 b     b    
3 c     c
test_db %>% 
  func_aaa2(a, "b", "a", "aaa") %>% show_query()
SELECT `a`, CASE
WHEN (`a` = 'a') THEN ('aaa')
WHEN (1) THEN (`a`)
END AS `b`
FROM `test`

关于r - 编写自定义 R 函数以在 dbplyr SQL 中使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61773954/

相关文章:

sql - 如何在 R Markdown block 中转义 SQL 代码中的字符?

r - 按列将匹配值求和到另一列

java - 如何在java中访问R(光栅对象)

r - 在 R 中设置数据帧的行时因子级别无效

r - 将标题垂直调整到绘图内部 - vjust 不起作用

r - 在ggplot中设置注释文本的宽度

sql - 在 SQL Server 中转换 MS Access 更新查询

mysql - 如何使用 dbplyr 连接到 mysql 数据库

r - 使用 R 连接到 Microsoft SQL Server( View 位于 Microsoft SQL Server Management Studio (SSMS) 中的数据库中)