在 R 中使用 dplyr::if_else() 根据另一个变量的值更改 POSIXct 时间戳的时区

Posted

技术标签:

【中文标题】在 R 中使用 dplyr::if_else() 根据另一个变量的值更改 POSIXct 时间戳的时区【英文标题】:Using dplyr::if_else() in R to change the time zone of POSIXct timestamps based on value of another variable 【发布时间】:2020-01-05 23:27:36 【问题描述】:

我正在处理一些 POSIXct 格式的时间戳。现在它们都显示在时区“UTC”中,但实际上有些已知位于“America/New_York”时区。我想更正时间戳,以便它们都读取为正确的时间。

我最初使用ifelse() 语句和lubridate::with_tz()。这没有按预期工作,因为ifelse() 没有在 POSIXct 中返回值。

然后我根据这里的其他帖子尝试了dplyr::if_else(),但这也没有按预期工作。

我可以使用with_tz() 将单个时间戳甚至时间戳列表更改为不同的时区(所以我知道它有效),但是当我在if_else() 中使用它时,输出会返回所有值给定“是”论点in if_else()

library(lubridate)
library(dplyr)

x <- data.frame("ts" = as.POSIXct(c("2017-04-27 13:44:00 UTC", 
"2017-03-10 12:22:00 UTC", "2017-03-22 10:24:00 UTC"), tz = "UTC"), 
"tz" = c("UTC","EST","UTC"))

x <- mutate(x, ts_New = if_else(tz == "UTC", with_tz(ts, "America/New_York"), ts))

预期结果低于 ts_New 将时间戳调整为新时区但仅当 tz = "UTC" 中的值时。 tz = "America/New_York" 的时间戳不应更改。

                   ts      tz                  ts_NEW
1 2017-04-27 13:44:00     UTC     2017-04-27 09:44:00
2 2017-03-10 12:22:00     EST     2017-03-10 12:22:00
3 2017-01-22 10:24:00     UTC     2017-03-22 06:24:00

实际结果低于所有 ts_New 时间戳调整到新时区的情况,而不管 tz 中的值如何

x
                   ts      tz                  ts_New
1 2017-04-27 13:44:00     UTC     2017-04-27 09:44:00
2 2017-03-10 12:22:00     EST     2017-03-10 07:22:00
3 2017-03-22 10:24:00     UTC     2017-03-22 06:24:00

【问题讨论】:

我在 SO 上遇到了一个 similar case。还有another similar case。似乎您只能在单个向量中使用一个时区。由于您尝试将时间戳转换为 EDT,因此即使您使用 ifelse 条件,所有时间戳最终都会变为 EDT 时间。这是我的猜测。 【参考方案1】:

这并不能回答您关于为什么 with_tz 不适用于 if_else 的原始问题,但这是一种解决方法。我们减去 4 小时(UTC 和 EST 之间的差异),其中tz == "UTC"

library(dplyr)
library(lubridate)

x %>%  mutate(ts_New = if_else(tz == "UTC", ts - hours(4), ts))

#                   ts  tz              ts_New
#1 2017-04-27 13:44:00 UTC 2017-04-27 09:44:00
#2 2017-03-10 12:22:00 EST 2017-03-10 12:22:00
#3 2017-03-22 10:24:00 UTC 2017-03-22 06:24:00

或者在基础R中

x$ts_New <- x$ts
inds <- x$tz == "UTC"
x$ts_New[inds] <- x$ts_New[inds] - 4 * 60 * 60

【讨论】:

感谢您的帮助!我最终基本上做了相反的事情。我使用您的代码将所有“EST”行更改为 UTC,然后使用with_tz() 将所有时间更改为“America/New_York”。这样做的好处是不仅可以显示正确的时间值,还可以存储正确的时区值并考虑夏令时。

以上是关于在 R 中使用 dplyr::if_else() 根据另一个变量的值更改 POSIXct 时间戳的时区的主要内容,如果未能解决你的问题,请参考以下文章

在 R 版本 3.4.4 中使用 R 包“效果”

r 在R中使用sqlite表

R 'mvpart' 包 - 在 R 3.1.x 中使用的任何选项?

在 R 中使用 mapreduce

译文怎样在R语言中使用SQL命令

r 在R中使用morph.io API