【问题标题】:Timezone in timestamps imported from csv从 csv 导入的时间戳中的时区
【发布时间】:2016-10-24 15:14:11
【问题描述】:

我有一个使用 fread 从 csv 文件(从 .xlsx 转换而来)导入的数据框。导入后,class(inputData$timestamp)Posixctattr(inputData$timestamp, "tzone")""

正如this 线程中所解释的,我正在尝试按天拆分数据帧,但它们在凌晨 2 点被拆分:

byDay <- split(inputData, as.Date(inputData$timestamp))
> byDay[[1]]
              timestamp value
1   2016-09-05 00:01:00     0
2   2016-09-05 00:02:00     0
3   2016-09-05 00:03:00     0
[...]
118 2016-09-05 01:58:00     0
119 2016-09-05 01:59:00     0

>byDay[[2]]
              timestamp value
120 2016-09-05 02:00:00     0
121 2016-09-05 02:01:00     0
122 2016-09-05 02:02:00     0
[...]
1558 2016-09-06 01:58:00    0
1559 2016-09-06 01:59:00    0

等等。

我了解日期与时间戳上显示的日期隐含不同:

> byDay[[1]]$timestamp[1]
"2016-09-05 00:01:00"
> as.Date(byDay[[1]]$timestamp[1])
"2016-09-04"

我对时区不感兴趣,所以我尝试将所有日期设置为 UTC:

> attr(inputData$timestamp, "tzone") <- "UTC"
> byDay <- split(inputData, as.Date(inputData$timestamp))
> byDay[[1]]
              timestamp apAvg
1   2016-09-04 22:01:00     0
2   2016-09-04 22:02:00     0
3   2016-09-04 22:03:00     0
[...]
117 2016-09-04 23:57:00     0
118 2016-09-04 23:58:00     0
119 2016-09-04 23:59:00     0

这意味着时间戳实际上从 22:00 开始。但是在 csv 文件中,第一个时间戳是05.09.2016 00:00:00,我看不到时区格式的迹象。 时区问题是否仍有可能来自 csv 文件? 还是我在 R 中处理错误的时间戳? 如何准确处理?

【问题讨论】:

  • 当你从字符串解析到 POSIXct 时,这是你真正应该解决的问题,而不是事后,或者你是否正在更改时区(即调整时间)变得非常模棱两可或者只是切换它(即更改数据)。而是在 as.POSIXct 中指定 tz 或您正在使用的任何解析函数。
  • 请参阅minimal reproducible example,了解如何在 SO 上提问。如果您的输入(或其缩减版)是 X,则显示 dput(X) 的输出。
  • @alistaire Setting tz = "" in as.POSIXct 解决了它。在解析时而不是稍后获得正确时区的更一致的方法。谢谢。
  • @G.Grothendieck 感谢您的提醒。但是我不能在这里发布 csv 文件,所以我不知道如何为其他人提供示例输入来重现问题。
  • 如果足够,显示dput(InputData)dput(head(InputData))的输出。

标签: r csv datetime posixct timestamp-with-timezone


【解决方案1】:

从字符串解析时,我会按照@alistaire 的建议设置时区。事实上,这似乎发生在

attr(inputData$timestamp, "tzone")""

之后,"" 是默认设置数据到您的本地时区。

问题是在使用as.DatePOSIXct 类输入时,tz 的默认值是"UTC",而不是您的本地时区。得到你想要的:

  1. 不要将数据的时区更改为"UTC"
  2. 在您的split 中使用as.Date(inputData$timestamp, tz="")

为了说明,假设数据是:

inputData<- structure(list(timestamp = structure(c(1473048000, 1473051600, 
1473055200, 1473058800, 1473062400, 1473066000, 1473069600, 1473073200, 
1473076800, 1473080400, 1473084000, 1473087600, 1473091200, 1473094800, 
1473098400, 1473102000, 1473105600, 1473109200, 1473112800, 1473116400, 
1473120000, 1473123600, 1473127200, 1473130800, 1473134400, 1473134460, 
1473134520, 1473134580), class = c("POSIXct", "POSIXt"), tzone = ""), 
    value = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
    0L)), .Names = c("timestamp", "value"), row.names = c(NA, 
-28L), class = "data.frame")
##             timestamp value
##1  2016-09-05 00:00:00     0
##2  2016-09-05 01:00:00     0
##3  2016-09-05 02:00:00     0
##4  2016-09-05 03:00:00     0
##5  2016-09-05 04:00:00     0
##6  2016-09-05 05:00:00     0
##7  2016-09-05 06:00:00     0
##8  2016-09-05 07:00:00     0
##9  2016-09-05 08:00:00     0
##10 2016-09-05 09:00:00     0
##11 2016-09-05 10:00:00     0
##12 2016-09-05 11:00:00     0
##13 2016-09-05 12:00:00     0
##14 2016-09-05 13:00:00     0
##15 2016-09-05 14:00:00     0
##16 2016-09-05 15:00:00     0
##17 2016-09-05 16:00:00     0
##18 2016-09-05 17:00:00     0
##19 2016-09-05 18:00:00     0
##20 2016-09-05 19:00:00     0
##21 2016-09-05 20:00:00     0
##22 2016-09-05 21:00:00     0
##23 2016-09-05 22:00:00     0
##24 2016-09-05 23:00:00     0
##25 2016-09-06 00:00:00     0
##26 2016-09-06 00:01:00     0
##27 2016-09-06 00:02:00     0
##28 2016-09-06 00:03:00     0

与:

attr(inputData$timestamp, "tzone")
##[1] ""

使用as.Date 和默认的tz 参数执行split

byDay <- split(inputData, as.Date(inputData$timestamp))
byDay[[1]]
##             timestamp value
##1  2016-09-05 00:00:00     0
##2  2016-09-05 01:00:00     0
##3  2016-09-05 02:00:00     0
##4  2016-09-05 03:00:00     0
## ...
##17 2016-09-05 16:00:00     0
##18 2016-09-05 17:00:00     0
##19 2016-09-05 18:00:00     0
##20 2016-09-05 19:00:00     0
byDay[[2]]
##             timestamp value
##21 2016-09-05 20:00:00     0
##22 2016-09-05 21:00:00     0
##23 2016-09-05 22:00:00     0
##24 2016-09-05 23:00:00     0
##25 2016-09-06 00:00:00     0
##26 2016-09-06 00:01:00     0
##27 2016-09-06 00:02:00     0
##28 2016-09-06 00:03:00     0

现在,我在美国东海岸,所以我现在在 EDT。这就是为什么 22:00:00 这里是 split 到 UTC 的第二天。对splitas.Date(inputData$timestamp,tz="") 执行相同的操作:

byDay <- split(inputData, as.Date(inputData$timestamp,tz=""))
byDay[[1]]
##             timestamp value
##1  2016-09-05 00:00:00     0
##2  2016-09-05 01:00:00     0
##3  2016-09-05 02:00:00     0
##4  2016-09-05 03:00:00     0
## ...
##21 2016-09-05 20:00:00     0
##22 2016-09-05 21:00:00     0
##23 2016-09-05 22:00:00     0
##24 2016-09-05 23:00:00     0
byDay[[2]]
##             timestamp value
##25 2016-09-06 00:00:00     0
##26 2016-09-06 00:01:00     0
##27 2016-09-06 00:02:00     0
##28 2016-09-06 00:03:00     0

【讨论】:

  • 我使用了@alistaire 的方法,仍然有帮助。
猜你喜欢
  • 2015-12-07
  • 2018-07-01
  • 2020-02-07
  • 2019-06-29
  • 2021-01-08
  • 2012-09-23
  • 1970-01-01
  • 1970-01-01
  • 2019-08-15
相关资源
最近更新 更多