r - 从没有润滑的日期减去 1 年

标签 r date dbplyr rpostgresql

我在数据库中有一个数据框,其中包含我使用 RPostgres 提取的日期维度。每个“日期”的格式为“YYYY-MM-DD”。我想添加一个新的日期列(标记为“lookback_date”),该日期比初始日期早一年。

需要明确的是,如果观察的“日期”是“2000-01-01”,我想向该观察添加一个新的“lookback_date”“1999-01-01”。不幸的是,我不知道该怎么做。通常,我会使用 Lubridate,但是据我所知,它不适用于 dbplyr。这是迄今为止我的代码的简化版本。我的实际代码中的所有内容在 mutate 函数之前都运行良好。

# Packages
library(dbplyr)
library(RPostgres)

# 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
base_data <- table %>%
  #Filter for pertinent data
  filter(date > as.Date("2018-01-01") & date <= as.Date("2020-01-01"))

modified_data <- base_data %>%
mutate(lookback_date = date - 365)

还有其他方法可以创建这个新的日期列吗?

谢谢!

最佳答案

您认为 lubridate 和 dbplyr 不能很好地协同工作(现在),这是正确的。因此,我使用 sql 片段进行大部分 dbplyr 日期操作。

基于this answerthis site ,从日期中添加/减去时间的 postgresql 语法是:

SELECT old_date + INTERVAL '1 day' AS new_date;

基于此我会尝试以下操作:

output = base_data %>% mutate(lookback_date = date - sql("INTERVAL '1 year'"))

当我使用模拟连接执行此操作时,它会生成正确的语法:

library(dplyr)
library(dbplyr)

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

output = df %>% mutate(new_date = my_dates - sql("INTERVAL '1 year'"))

show_query(output)
# <SQL>
# SELECT `my_num`, `my_dates`, `my_dates` - INTERVAL '1 year' AS `new_date`
# FROM `df`

更新:根据评论,您首先要从日期时间转换为日期。

看来 dbplyr 确实支持将 as.Date 转换为 PostgreSQL(as.Date 是基础 R 的一部分,而不是 lubridate 的一部分)。因此,您可以使用以下命令将列转换(转换)为日期:

library(dplyr)
library(dbplyr)

df = data.frame(my_str = c('2000-01-01','2000-02-02','2000-03-03'))
df = tbl_lazy(df, con = simulate_postgres())

output = df %>% mutate(my_date = as.Date(my_str))

show_query(output)
# <SQL>
# SELECT `my_str`, CAST(`my_str` AS DATE) AS `my_date`
# FROM `df`

似乎 PostgreSQL 不允许添加一年的间隔。一种替代方法是从日期中提取年、月和日,在年份上加一,然后重新组合。

遵循这两个引用文献( postgre date referencesdate_part fuction )和 this答案,您可能想要如下所示的内容:

output = df %>%
  mutate(the_year = DATE_PART('year', my_date),
         the_month = DATE_PART('month', my_date),
         the_day = DATE_PART('day', my_date)) %>%
  mutate(new_date = MAKE_DATE(the_year + 1, the_month, the_day)

关于r - 从没有润滑的日期减去 1 年,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66179558/

相关文章:

r - 从 R 中保存的绘图创建视频

r - 为什么数字 1e9999...(31 个 9)会在 R 中引起问题?

r - 为什么 `conf.level` 参数对 `binom::binom.confint` 函数的结果没有影响?

php - WooCommerce Bookings - 在自定义日期格式上用 PHP 比较两个时间戳

r - 无法访问 dbplyr 中的字符串方法

r - 如何使用 dbplyr 删除仅包含 NA 的所有列?

r - Grep 文本并放入数据框中

javascript - 根据语句的顺序,函数返回不正确的月份

c - 如何使用当前区域设置打印日期?

sql - 使用 dbplyr 生成 CROSS JOIN 查询