我有两段代码理论上可以做同样的事情:
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())
返回空字符串Sys.timezone()
返回本地时区,在我的例子中为“欧洲/伦敦”tz(as.Date(now()))
返回“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 小时时区差异以及接近午夜发生的事件等)。
关于r - 聚合函数和时区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71527832/