0

为此打开了一个问题。但如果这是操作员错误而不是包的问题,​​我将在此处发布编码建议。

最新的 (v2.1) 更新dbplyr应该增加对across相关功能的支持。但是,当我尝试使用它时,我仍然会遇到错误。

我应该使用不同的语法吗?有解决方法吗?

library(dplyr, warn.conflicts = FALSE)
library(bigrquery)

set.seed(02042021)

Sys.setenv(BIGQUERY_TEST_PROJECT = "elite-magpie-257717")
bq_deauth()
bq_auth(email="ariel.balter@gmail.com")

conn = DBI::dbConnect(
  bigrquery::bigquery(),
  project = bq_test_project(),
  dataset = "test_dataset"
)

my_table = data.frame(
  A = replicate(10, paste(sample(letters[1:3], 3, replace=T), collapse="")),
  B = replicate(10, paste(sample(letters[1:3], 3, replace=T), collapse="")),
  C = replicate(10, paste(sample(letters[1:3], 3, replace=T), collapse="")),
  D = runif(10)
)
my_table
#>      A   B   C         D
#> 1  bcb cbb bbb 0.3620390
#> 2  aac aac bba 0.5505868
#> 3  aca abb bcb 0.4028455
#> 4  bca baa bbb 0.3247477
#> 5  bcc cac ccc 0.6861223
#> 6  cac bba baa 0.6970764
#> 7  bcb bbc acc 0.6873332
#> 8  bca acb acb 0.5391651
#> 9  cba ccc abc 0.9442450
#> 10 cca cbc bcc 0.6319561

my_table %>%
  mutate(
    has_ab = if_any(everything(), ~grepl("ab", .))
  )
#>      A   B   C         D has_ab
#> 1  bcb cbb bbb 0.3620390  FALSE
#> 2  aac aac bba 0.5505868  FALSE
#> 3  aca abb bcb 0.4028455   TRUE
#> 4  bca baa bbb 0.3247477  FALSE
#> 5  bcc cac ccc 0.6861223  FALSE
#> 6  cac bba baa 0.6970764  FALSE
#> 7  bcb bbc acc 0.6873332  FALSE
#> 8  bca acb acb 0.5391651  FALSE
#> 9  cba ccc abc 0.9442450   TRUE
#> 10 cca cbc bcc 0.6319561  FALSE

my_table %>%
  mutate(
    has_ab = if_any(where(is.numeric), ~grepl("ab", .))
  )
#>      A   B   C         D has_ab
#> 1  bcb cbb bbb 0.3620390  FALSE
#> 2  aac aac bba 0.5505868  FALSE
#> 3  aca abb bcb 0.4028455  FALSE
#> 4  bca baa bbb 0.3247477  FALSE
#> 5  bcc cac ccc 0.6861223  FALSE
#> 6  cac bba baa 0.6970764  FALSE
#> 7  bcb bbc acc 0.6873332  FALSE
#> 8  bca acb acb 0.5391651  FALSE
#> 9  cba ccc abc 0.9442450  FALSE
#> 10 cca cbc bcc 0.6319561  FALSE

dbRemoveTable(
  conn=conn,
  name="test_dataset.mytable",
  value=my_table,
  overwrite=T
)

dbWriteTable(
  conn=conn,
  name="test_dataset.mytable",
  value=my_table,
  overwrite=T
)

my_table_bq = tbl(conn, "mytable")


my_table_bq %>%
  mutate(
    has_ab = if_any(everything(), ~grepl("ab", .))
  )
#> Error in UseMethod("escape"): no applicable method for 'escape' applied to an object of class "formula"

my_table_bq %>%
  mutate(
    has_ab = if_any(where(is.numeric), ~grepl("ab", .))
  )
#> Error in UseMethod("escape"): no applicable method for 'escape' applied to an object of class "function"

reprex 包于 2021-02-05 创建(v1.0.0)

4

2 回答 2

2

我认为目前 dbplyr(2.1.0 版)不可能做到这一点。这是我的测试用例:

(一)工作案例

# shared setup
library(dplyr)
library(dbplyr)
data(iris)
df = tbl_lazy(iris, con = simulate_mssql()) %>%
  select(Sepal.Length)

df %>%
  mutate(new = Sepal.Length + 1) %>%
  show_query()

返回预期的 SQL:

<SQL>
SELECT `Sepal.Length`, `Sepal.Length` + 1.0 AS `new`
FROM `df`

(2) 介绍一个简单的一切

df %>%
  mutate(new = if_any(everything(), TRUE)) %>%
  show_query()

返回无效的 sql,因为不存在if_any或不everything存在翻译:

<SQL>
SELECT `Sepal.Length`, if_any(everything(), 1) AS `new`
FROM `df`

(3)简单的is.numeric

df %>%
  mutate(new = if_any(where(is.numeric), TRUE)) %>%
  show_query()

错误,因为is.numeric作为函数传递

UseMethod(“escape”)中的错误:没有适用于“escape”的方法应用于“function”类的对象

(4) 将 TRUE 包裹在一个返回 TRUE 的函数中

df %>%
  mutate(new = if_any(everything(), ~{TRUE})) %>%
  show_query()

错误,因为不~{...}存在隐式函数的翻译:

UseMethod(“escape”)中的错误:没有适用于“escape”的方法应用于“公式”类的对象

于 2021-02-06T00:56:49.623 回答
1

这是基于这个关于 dynamic的答案case_when的潜在解决方法。

list_of_columns = colnames(df)

text_to_match = "ab"

cases = paste0("`", list_of_columns, "` %LIKE% '%", text_to_match, "%' ~ 1")
cases = c(cases, "1 == 1 ~ 0")

output = df %>%
    mutate(new_col = case_when(
      !!!rlang::parse_exprs(cases)
    ))

有关此技术的另一个示例,或者作为可重用函数的一部分,请查看collapse_indicator_columns我的 dbplyr_helpers repo的函数。

于 2021-02-06T05:44:31.077 回答