将函数与 dbplyr 中的现有 sql 翻译组合在一起的函数

Ale*_*lex 6 r dplyr dbplyr

出现这个问题是因为我希望为方便起见创建一个函数:

as.numeric_psql <- function(x) {

   return(as.numeric(as.integer(x)))
}
Run Code Online (Sandbox Code Playgroud)

将远程 postgres 表中的布尔值转换为数字。需要转换为整数的步骤如下:

在数字和布尔值之间没有定义直接转换。您可以使用整数作为中间立场。( /sf/answers/1350347001/ )

当然,此功能在本地按预期工作:

copy_to(con_psql, cars, 'tmp_cars')

tmp_cars_sdf <-
    tbl(con_psql, 'tmp_cars')


tmp_cars_sdf %>%
    mutate(low_dist = dist < 5) %>%
    mutate(low_dist = as.numeric(as.integer(low_dist)))

# # Source:   lazy query [?? x 3]
# # Database: postgres 9.5.3
#     speed  dist low_dist
#     <dbl> <dbl>    <dbl>
# 1     4     2        1
# 2     4    10        0
# 3     7     4        1
# 4     7    22        0
# 5     8    16        0

cars %>%
    mutate(low_dist = dist < 5) %>%
    mutate(low_dist = as.numeric_psql(low_dist)) %>%
    head(5)

#   speed dist low_dist
# 1     4    2        1
# 2     4   10        0
# 3     7    4        1
# 4     7   22        0
# 5     8   16        0
Run Code Online (Sandbox Code Playgroud)

但是,在远程数据帧上使用时它不起作用,因为as.numeric_psql它不在 sql 翻译列表中,因此被逐字传递给查询:

> tmp_cars_sdf %>%
+     mutate(low_dist = dist < 5) %>%
+     mutate(low_dist = as.numeric_psql(low_dist))
Error in postgresqlExecStatement(conn, statement, ...) : 
  RS-DBI driver: (could not Retrieve the result : ERROR:  syntax error at or near "as"
LINE 1: SELECT "speed", "dist", as.numeric_psql("low_dist") AS "low_...
                                ^
)
Run Code Online (Sandbox Code Playgroud)

我的问题是是否存在一种简单的方法(即不定义自定义 sql 翻译)让 dplyr 理解该函数as.numeric_psql是具有现有 sql 翻译的函数的组合,并改为使用这些翻译。

eip*_*i10 1

避免错误的一种方法是将函数设置为在数据帧上操作,而不是在内部 mutate 上操作。例如:

\n\n
copy_to(con_psql, cars, 'tmp_cars')\n\ntmp_cars_sdf <- tbl(con_psql, 'tmp_cars')\n\nas.numeric_psql <- function(data, x) {\n  return(data %>% mutate({{x}} := as.numeric(as.integer({{x}}))))\n}\n\ntmp_cars_sdf %>%\n  mutate(low_dist = dist < 5) %>%\n  as.numeric_psql(low_dist)\n\n#> # Source:   lazy query [?? x 3]\n#> # Database: sqlite 3.30.1 [:memory:]\n#>    speed  dist low_dist\n#>    <dbl> <dbl>    <dbl>\n#>  1     4     2        1\n#>  2     4    10        0\n#>  3     7     4        1\n#>  4     7    22        0\n#>  5     8    16        0\n#>  6     9    10        0\n#>  7    10    18        0\n#>  8    10    26        0\n#>  9    10    34        0\n#> 10    11    17        0\n#> # \xe2\x80\xa6 with more rows\n
Run Code Online (Sandbox Code Playgroud)\n\n

请注意,在您的示例中,数据库版本low_dist在创建时已被编码为整数,而不是像标准 R 数据框架中那样符合逻辑:

\n\n
tmp_cars_sdf %>%\n  mutate(low_dist = dist < 5) \n#> # Source:   lazy query [?? x 3]\n#> # Database: sqlite 3.30.1 [:memory:]\n#>    speed  dist low_dist\n#>    <dbl> <dbl>    <int>\n#>  1     4     2        1\n#>  2     4    10        0\n#>  3     7     4        1\n#>  4     7    22        0\n#>  5     8    16        0\n#>  6     9    10        0\n#>  7    10    18        0\n#>  8    10    26        0\n#>  9    10    34        0\n#> 10    11    17        0\n#> # \xe2\x80\xa6 with more rows\n\ncars %>%\n  mutate(low_dist = dist < 5) %>% head\n#>   speed dist low_dist\n#> 1     4    2     TRUE\n#> 2     4   10    FALSE\n#> 3     7    4     TRUE\n#> 4     7   22    FALSE\n#> 5     8   16    FALSE\n#> 6     9   10    FALSE\n
Run Code Online (Sandbox Code Playgroud)\n