0

filter()按日期查询并使用函数提供该日期时,我看到一个预期的错误:

library(tidyverse)
library(bigrquery)

table1 %>% 
  filter(date > as.character(today() - 730)) %>% 
  tally()

# Error: No matching signature for operator - for argument types: DATE, FLOAT64. 
Supported signatures: INT64 - INT64; NUMERIC - NUMERIC; FLOAT64 - FLOAT64 at [29:29] [invalidQuery]

但是当日期作为字符串提供时,它可以正常工作

table1 %>%
  filter(date > '2018-04-11') %>% 
  tally()

#          n
#      <int>
#  623451234

能确认as.character(today() - 730)'2018-04-11'一样

> identical(as.character(today() - 730), '2018-04-11')
[1] TRUE

以下解决方法是可以的,但对于较大的代码库会变得混乱:

date_from <- as.character(today() - 730)

table1 %>% 
  filter(date > date_from) %>% 
  tally()

问题

为什么当filter()通过类似 的函数提供日期时会看到错误as.character(today() - 730),而当日期由字符串提供时却没有?

笔记

  • 类似的问题在这里
  • 我尝试替换as.character(today() - 730)as.Date(today() - 730)得到完全相同的错误
4

1 回答 1

1

dbplyr尽管您的问题中没有提到它,但您已将其标记为。如果您正在使用,dbplyr那么问题是由于如何dbplyr从 R 转换为数据库语言(在您的情况下为 bigquery)。

dbplyr有一系列进行转换的内置翻译(例如filter被翻译成WHERE从句)。这些翻译能够根据您的示例从变量中查找值:

date_from <- as.character(today() - 730)
table1 %>% filter(date > date_from)

但无法判断子功能是评估、翻译还是保持原样。因此,根据文档,dbplyr 保留任何“未知”功能。这意味着

table1 %>% filter(date > as.character(today() - 730))

可能会被翻译成类似的东西

SELECT ...
FROM ...
WHERE date > as.character(today() - 730)

这会导致错误,因为这不是数据库的有效语法。

您可以使用以下命令检查翻译show_query()

table1 %>% filter(date > as.character(today() - 730)) %>% show_query()

这个问题询问了一个非常相似的问题 - 翻译是为他们正在使用的函数定义的,但不是为充当包装器的自定义函数定义的。能够定义自定义翻译将解决这两个问题,但目前这似乎是不可能的。

有两种解决方法:

  1. dbplyr 文档中,您可以使用sql()插入原始 SQL 字符串(不会被翻译)。
  2. 您可以编写自己的函数来返回自定义表定义。请参阅此答案的“创建自定义函数”部分。
于 2020-04-11T00:48:10.573 回答