聚合函数和时区
Aggregate function and timezone
我有两段代码理论上做同样的事情:
Mn_min_max_D <- with(Mn, aggregate(Depth ~ as.Date(Date_time), FUN = function(x) c(Min = min(x), Max = max(x))))
Mn_min_max_D <- do.call(data.frame, Mn_min_max_D)
names(Mn_min_max_D)[names(Mn_min_max_D) == "as.Date.Date_time."] <- "Date"
min_max_D <- with(Mn, aggregate(Depth ~ as.Date(Date), FUN = function(x) c(Min = min(x), Max = max(x))))
min_max_D <- do.call(data.frame, min_max_D)
names(Mn_min_max_D)[names(min_max_D) == "as.Date.Date_time."] <- "Date"
但是输出值不同。在检查最大深度时,我发现由于某种原因,第一段代码忽略了时区。
例如,最大深度发生在“2013-10-26 22:33:00”,但经过时区校正后,这实际上是“2013-10-27 07:33:00”。
$Date 值来自此代码:
Mn$Date_time <- as.POSIXct(Mn$Date_time, format="%Y-%m-%d %H:%M:%S", tz = "Asia/Tokyo")
Mn$Date <- format(as.POSIXct(Mn$Date_time, format="%YYYY/%m/%d %H:%M:%S"), format = "%Y/%m/%d")
Mn$Date <- as.Date(Mn$Date, "%Y/%m/%d")
似乎删除时间的过程可以修复日期。我需要了解问题的根源,以确保我以后不会犯错。
我想我可能需要用 tz 进行 %>% 变异,但目前不明白怎么做。或者可能使用 dplyr 聚合而不是如下所示,但我已经尝试过并且结果是相同的。
test <- Mn %>% group_by(as.Date(Date_time))%>% dplyr::summarise(min = min(Depth), max = max(Depth))
示例数据:
Date_time Depth
2013-10-14 12:30:00 64.45
2013-10-14 12:30:05 65.95
2013-10-14 12:30:10 65.95
2013-10-14 12:30:15 66.45
2013-10-14 12:30:20 67.95
2013-10-14 12:30:25 66.95
在目前的格式中,数据不包含时区,因此使用默认时区。如果您知道这些时间戳的时区,最好对其进行明确控制。
dta <- with(
asNamespace("readr"),
read_table(
file = "
Date_time Depth
2013-10-14-12:30:00 64.45
2013-10-14-12:30:05 65.95
2013-10-14-12:30:10 65.95
2013-10-14-12:30:15 66.45
2013-10-14-12:30:20 67.95
2013-10-14-12:30:25 66.95",
col_types = cols(
Date_time = col_datetime(format = "%Y-%m-%d-%H:%M:%S"),
Depth = col_double()
)
)
)
library("lubridate")
library("tidyverse")
dta %>%
mutate(DT_tz = force_tz(Date_time, tzone = "GMT"),
DT_tz_NYC = with_tz(Date_time, tzone = "America/New_York"))
说明
考虑以下因素:
tz(now())
returns 一个空字符串
Sys.timezone()
returns 本地时区,"Europe/London" 在我的例子中
tz(as.Date(now()))
returns "UTC"
不指定时区 R 取决于您的本地设置
as.POSIXlt(Sys.time(), "America/New_York")
# "2022-03-18 12:43:10 EDT"
as.POSIXlt(Sys.time())
# "2022-03-18 16:43:16 GMT"
这可能有点繁琐。
tz(as.POSIXlt(Sys.time()))
# [1] "Europe/London"
tz(as.Date(as.POSIXlt(Sys.time())))
# "UTC"
特别值得一提的是,使用 as.Date
会去除时区信息。
tz(as.Date(as.POSIXlt(Sys.time())))
"UTC"
tz(as.Date(as.POSIXlt(Sys.time()), tz = "Africa/Abidjan"))
"UTC"
解决方案
如果处理时间戳,始终建议确保在该数据中重新编码时区信息,或者作为替代方案,在脚本中明确说明不太可靠的选项。就个人而言,我认为时区组件是时间戳的组成部分,应该与数据一起驻留。当本地化时间戳不同时,从时间戳中剥离时区信息会导致混淆。显着差异可能会导致不同的日期(考虑 2 小时时区差异和接近午夜发生的事件等)。
我有两段代码理论上做同样的事情:
Mn_min_max_D <- with(Mn, aggregate(Depth ~ as.Date(Date_time), FUN = function(x) c(Min = min(x), Max = max(x))))
Mn_min_max_D <- do.call(data.frame, Mn_min_max_D)
names(Mn_min_max_D)[names(Mn_min_max_D) == "as.Date.Date_time."] <- "Date"
min_max_D <- with(Mn, aggregate(Depth ~ as.Date(Date), FUN = function(x) c(Min = min(x), Max = max(x))))
min_max_D <- do.call(data.frame, min_max_D)
names(Mn_min_max_D)[names(min_max_D) == "as.Date.Date_time."] <- "Date"
但是输出值不同。在检查最大深度时,我发现由于某种原因,第一段代码忽略了时区。 例如,最大深度发生在“2013-10-26 22:33:00”,但经过时区校正后,这实际上是“2013-10-27 07:33:00”。
$Date 值来自此代码:
Mn$Date_time <- as.POSIXct(Mn$Date_time, format="%Y-%m-%d %H:%M:%S", tz = "Asia/Tokyo")
Mn$Date <- format(as.POSIXct(Mn$Date_time, format="%YYYY/%m/%d %H:%M:%S"), format = "%Y/%m/%d")
Mn$Date <- as.Date(Mn$Date, "%Y/%m/%d")
似乎删除时间的过程可以修复日期。我需要了解问题的根源,以确保我以后不会犯错。
我想我可能需要用 tz 进行 %>% 变异,但目前不明白怎么做。或者可能使用 dplyr 聚合而不是如下所示,但我已经尝试过并且结果是相同的。
test <- Mn %>% group_by(as.Date(Date_time))%>% dplyr::summarise(min = min(Depth), max = max(Depth))
示例数据:
Date_time Depth
2013-10-14 12:30:00 64.45
2013-10-14 12:30:05 65.95
2013-10-14 12:30:10 65.95
2013-10-14 12:30:15 66.45
2013-10-14 12:30:20 67.95
2013-10-14 12:30:25 66.95
在目前的格式中,数据不包含时区,因此使用默认时区。如果您知道这些时间戳的时区,最好对其进行明确控制。
dta <- with(
asNamespace("readr"),
read_table(
file = "
Date_time Depth
2013-10-14-12:30:00 64.45
2013-10-14-12:30:05 65.95
2013-10-14-12:30:10 65.95
2013-10-14-12:30:15 66.45
2013-10-14-12:30:20 67.95
2013-10-14-12:30:25 66.95",
col_types = cols(
Date_time = col_datetime(format = "%Y-%m-%d-%H:%M:%S"),
Depth = col_double()
)
)
)
library("lubridate")
library("tidyverse")
dta %>%
mutate(DT_tz = force_tz(Date_time, tzone = "GMT"),
DT_tz_NYC = with_tz(Date_time, tzone = "America/New_York"))
说明
考虑以下因素:
tz(now())
returns 一个空字符串Sys.timezone()
returns 本地时区,"Europe/London" 在我的例子中tz(as.Date(now()))
returns "UTC"
不指定时区 R 取决于您的本地设置
as.POSIXlt(Sys.time(), "America/New_York")
# "2022-03-18 12:43:10 EDT"
as.POSIXlt(Sys.time())
# "2022-03-18 16:43:16 GMT"
这可能有点繁琐。
tz(as.POSIXlt(Sys.time()))
# [1] "Europe/London"
tz(as.Date(as.POSIXlt(Sys.time())))
# "UTC"
特别值得一提的是,使用 as.Date
会去除时区信息。
tz(as.Date(as.POSIXlt(Sys.time())))
"UTC"
tz(as.Date(as.POSIXlt(Sys.time()), tz = "Africa/Abidjan"))
"UTC"
解决方案
如果处理时间戳,始终建议确保在该数据中重新编码时区信息,或者作为替代方案,在脚本中明确说明不太可靠的选项。就个人而言,我认为时区组件是时间戳的组成部分,应该与数据一起驻留。当本地化时间戳不同时,从时间戳中剥离时区信息会导致混淆。显着差异可能会导致不同的日期(考虑 2 小时时区差异和接近午夜发生的事件等)。