使用 Dbplyr 时将日期转换为年-季度格式

问题描述

我在数据库中有一个数据框,其中包含我使用 RPostgres/Rpostgresql 和 dbplyr 提取的日期维度。每个日期的格式为“YYYY-MM-DD”,我需要添加一个新的日期(或字符)维度,以反映年季度格式“YYYY-Q”(带破折号,而不是期间)。

鉴于我不能将 lubridate 与 dbplyr 一起使用,我将如何实现这一点?

感谢您的帮助!这是我目前所拥有的简化版本,因此您可以看到我正在使用哪些包以及我如何连接到数据库

# Packages
library(RPostgres)
library(RPostgresql)
library(dplyr)
library(dbplyr)

# Connect to db 
drv <- dbDriver("Postgres")

# Setup connect to db
conn <- dbConnect(drv,dbname = etc,)

# Define table to use in db
table <- tbl(conn,in_schema("xyz","abc"))

#Select columns and filter
df <- table %>%
  #Filter for pertinent data
  filter(date > as.Date("2018-01-01") & date <= as.Date("2020-01-01")) 

 

解决方法

你能使用zoo的{​​{1}}吗?

as.yearqtr

要获取特定格式的数据,您可以使用 zoo::as.yearqtr(Sys.Date()) #[1] "2021 Q2" :

format
,

因为 dbplyr 不翻译 lubridate,所以我经常用于日期操作的方法是 SQL 的小片段。您可以看到此 here 的示例。

由于您需要从现有日期中提取年份和季度,因此第一步是识别执行此操作的 postgresql 代码片段。请注意,不同版本的 SQL 在处理日期时使用不同的函数,因此此代码将特定于 postgresql。

基于 this linkthis link,似乎有两种方法可以提取日期的组成部分:

  1. EXTRACT(YEAR FROM date_column)
  2. DATE_PART('year',date_column)

我将使用下面的第一种方法。

当我使用 SQL 片段时,我还将按照 this link 使用 SQL 进行连接。例如:CONCAT(year_column '-',quarter_column)。所以我的输出将是一列文本类型。

将这些组合在一起给出:

library(dplyr)
library(dbplyr)

df = data.frame(my_num = c(1,2,3),my_dates = c('2000-01-01','2000-02-02','2000-03-03'))

df = tbl_lazy(df,con = simulate_postgres()) # simulated remote table

output = df %>%
  mutate(the_quarter = sql("EXTRACT(QUARTER FROM my_dates)"),the_year = sql("EXTRACT(YEAR FROM my_dates)")) %>%
  mutate(quarter = CONCAT(the_year,'-',the_quarter))

调用 show_query(output) 允许我们检查生成的 postgresql 查询:

SELECT `my_num`,`my_dates`,`the_quarter`,`the_year`,CONCAT(`the_year`,`the_quarter`) AS `quarter`
FROM (
    SELECT `my_num`,EXTRACT(QUARTER FROM my_dates) AS `the_quarter`,EXTRACT(YEAR FROM my_dates) AS `the_year`
    FROM `df`
) `q01

但没有那么好的格式。据我所知,这是一个有效的 postgresql 函数,所以我们可以期待它的工作。

根据您的应用,您可能还需要考虑 this question,尤其是 this answer。因为可能有更好的替代 'YYYY-Q' 格式。

,

一堆 lubridate 函数在 dbplyr 中被赋予了 SQL 翻译。所以下面的代码对我有用。

这样做的一个优点是如果谨慎使用,您可以将数据的位置移动到最有效的位置(在服务器上或本地)。

library(dplyr,warn.conflicts = FALSE)
library(DBI)
library(lubridate)
#> 
#> Attaching package: 'lubridate'
#> The following objects are masked from 'package:base':
#> 
#>     date,intersect,setdiff,union

pg <- dbConnect(RPostgres::Postgres(),bigint = "integer")
calls <- tbl(pg,sql("SELECT * FROM streetevents.calls"))

calls %>%
    mutate(yq = paste0(year(start_date),"-",quarter(start_date))) %>%
    select(start_date,yq)
#> # Source:   lazy query [?? x 2]
#> # Database: postgres [iangow@/tmp:5432/crsp]
#>    start_date          yq    
#>    <dttm>              <chr> 
#>  1 2013-09-10 19:30:00 2013-3
#>  2 2003-10-22 15:00:00 2003-4
#>  3 2009-10-22 16:00:00 2009-4
#>  4 2017-02-09 06:00:00 2017-1
#>  5 2010-02-22 22:00:00 2010-1
#>  6 2016-08-08 20:30:00 2016-3
#>  7 2016-05-11 13:00:00 2016-2
#>  8 2012-05-15 16:20:00 2012-2
#>  9 2004-08-19 21:00:00 2004-3
#> 10 2017-07-06 13:30:00 2017-3
#> # … with more rows

calls %>%
    collect(n = 10) %>%
    mutate(yq = paste0(year(start_date),yq)
#> # A tibble: 10 x 2
#>    start_date          yq    
#>    <dttm>              <chr> 
#>  1 2013-09-10 19:30:00 2013-3
#>  2 2003-10-22 15:00:00 2003-4
#>  3 2009-10-22 16:00:00 2009-4
#>  4 2017-02-09 06:00:00 2017-1
#>  5 2010-02-22 22:00:00 2010-1
#>  6 2016-08-08 20:30:00 2016-3
#>  7 2016-05-11 13:00:00 2016-2
#>  8 2012-05-15 16:20:00 2012-2
#>  9 2004-08-19 21:00:00 2004-3
#> 10 2017-07-06 13:30:00 2017-3

reprex package (v1.0.0) 于 2021 年 4 月 3 日创建