r, write_csv 正在将所有 times/dates 更改为 UTC
r, write_csv is changing all times/dates to UTC
我发现了一个非常烦人的问题,我想与社区分享。这是一个我已经找到可接受的解决方案(详见下文)的问题,但我现在有几个后续问题。我对时间戳和 POSIX 变量的了解有限,特别是 plyr、dplyr 和 readr 如何处理这些。
在使用 POSIX 变量(又名日期和时间戳)时,我发现 readr 的 write_csv 将这些变量更改为 UTC 时间。
我正在从 API 下载数据并保留时间戳。每次抓取数据时,我都会将其绑定到现有文件并保存该文件。我的时区是 MDT,我正在使用 MDT 时间请求数据,然后我试图将其绑定到 UTC 时间的文件,但时间不匹配......它变得混乱和令人沮丧。本质上,我试图创建的漂亮时间戳数据库正在变成一堆垃圾。
为了解决这个问题,我使用以下方法将 POSIX 时间列转换为字符列:
df.time <- as.character(df.time)
这使我能够将文件保存在与 API 返回给我的时间戳一致的时区中。
这让我想到了以下一系列问题:
- 有没有可以跨时区加入POSIX变量的程序?例如,如果是中午 MDT,则为下午 6 点 UTC。我可以根据这些时间戳加入两个数据帧,而不必先将它们转换为同一时区吗?
- 是否可以防止 write_csv 将 POSIX 变量更改为 UTC?
- 是否有不更改 POSIX 个变量的 csv 写入函数?
编辑:我已经包含了我正在谈论的一些示例数据:
> df1 <- as.data.frame(fromJSON("https://api.pro.coinbase.com/products/BTC-USD/candles?start=2018-07-23&12:57:00?stop=2018-07-23&19:34:58granularity=300"))
> colnames(df1) <- c("time", "low", "high", "open", "close", "volume")
> df1$time <- anytime(df1$time)
> df1Sort <- df1[order(df1$time),]
> head(df1Sort, 5)
time low high open close volume
299 2018-07-23 16:13:00 7747.00 7747.01 7747.01 7747.01 9.2029168
298 2018-07-23 16:14:00 7743.17 7747.01 7747.00 7747.01 7.0205668
297 2018-07-23 16:15:00 7745.47 7745.73 7745.67 7745.73 0.9075707
296 2018-07-23 16:16:00 7745.72 7745.73 7745.72 7745.73 4.6715157
295 2018-07-23 16:17:00 7745.72 7745.73 7745.72 7745.72 2.4921921
> write_csv(df1Sort, "df1Sort.csv", col_names = TRUE)
> df2 <- read_csv("df1Sort.csv", col_names = TRUE)
Parsed with column specification:
cols(
time = col_datetime(format = ""),
low = col_double(),
high = col_double(),
open = col_double(),
close = col_double(),
volume = col_double()
)
> head(df2, 5)
# A tibble: 5 x 6
time low high open close volume
<dttm> <dbl> <dbl> <dbl> <dbl> <dbl>
1 2018-07-23 22:13:00 7747 7747 7747 7747 9.20
2 2018-07-23 22:14:00 7743 7747 7747 7747 7.02
3 2018-07-23 22:15:00 7745 7746 7746 7746 0.908
4 2018-07-23 22:16:00 7746 7746 7746 7746 4.67
5 2018-07-23 22:17:00 7746 7746 7746 7746 2.49
"Is there a program that can join POSIX variables across time zones... without having to convert them to the same time zone first?"
也许吧?但如果是这样,他们几乎可以肯定只是在幕后转换为 UTC 并且只是向您隐藏它。我不知道 R 中有这样的事情。(data.table
是我所知道的唯一可以加入除完全相等之外的任何东西的包,而且它没有这个功能。)如果我是你,我只是将所有内容都转换为一个时区 - 可能是 UTC。
阅读更多最佳实践
"Is it possible to prevent write_csv from changing POSIX variables to UTC?"
不是内置的。 ?write_csv
文档非常清楚:它没有为此列出任何选项,而是说 "POSIXct's are formatted as ISO8601."
"Is there a csv write function that doesn't change POSIX variables?"
当然,内置的 write.csv
不会更改为 UTC(我认为它使用系统设置),并且 data.table::fwrite
提供了很多选项。如果您想控制日期的保存方式,我认为最好的办法是将它们转换为您想要的任何格式的 character
,然后任何编写函数都应该可以很好地处理它们。您应该查看 ?data.table::fwrite
文档,它提供了很好的信息。他们警告说 "write.csv"
选项可能会很慢。
您应该在问题中包含可重现的示例。这是一个:
t = as.POSIXct("2018-01-01 01:30:00", tz = "Africa/Addis_Ababa")
t
# [1] "2018-01-01 01:30:00 EAT"
d = data.frame(t)
library(readr)
write_csv(d, "tz_test.csv")
system("head tz_test.csv")
# 2017-12-31T22:30:00Z
library(data.table)
fwrite(d, "tz_test_dt.csv", dateTimeAs = "write.csv")
system("head tz_test_dt.csv")
# t
# 2018-01-01 01:30:00
write.csv(d, "tz_test_base.csv")
system("head tz_test_base.csv")
# "","t"
# "1",2018-01-01 01:30:00
您似乎在使用 tidyverse 中的库;你看过 lubridate 库了吗?
as_date() 的帮助文件可以帮助您在 append/join 数据之前将日期时间变量转换为所需的时区。
例如:
> dt_utc <- ymd_hms("2010-08-03 00:50:50")
> dt_utc
[1] "2010-08-03 00:50:50 UTC"
> as_datetime(dt_utc, tz = "Australia/Melbourne")
[1] "2010-08-03 10:50:50 AEST"
我发现了一个非常烦人的问题,我想与社区分享。这是一个我已经找到可接受的解决方案(详见下文)的问题,但我现在有几个后续问题。我对时间戳和 POSIX 变量的了解有限,特别是 plyr、dplyr 和 readr 如何处理这些。
在使用 POSIX 变量(又名日期和时间戳)时,我发现 readr 的 write_csv 将这些变量更改为 UTC 时间。
我正在从 API 下载数据并保留时间戳。每次抓取数据时,我都会将其绑定到现有文件并保存该文件。我的时区是 MDT,我正在使用 MDT 时间请求数据,然后我试图将其绑定到 UTC 时间的文件,但时间不匹配......它变得混乱和令人沮丧。本质上,我试图创建的漂亮时间戳数据库正在变成一堆垃圾。
为了解决这个问题,我使用以下方法将 POSIX 时间列转换为字符列:
df.time <- as.character(df.time)
这使我能够将文件保存在与 API 返回给我的时间戳一致的时区中。
这让我想到了以下一系列问题:
- 有没有可以跨时区加入POSIX变量的程序?例如,如果是中午 MDT,则为下午 6 点 UTC。我可以根据这些时间戳加入两个数据帧,而不必先将它们转换为同一时区吗?
- 是否可以防止 write_csv 将 POSIX 变量更改为 UTC?
- 是否有不更改 POSIX 个变量的 csv 写入函数?
编辑:我已经包含了我正在谈论的一些示例数据:
> df1 <- as.data.frame(fromJSON("https://api.pro.coinbase.com/products/BTC-USD/candles?start=2018-07-23&12:57:00?stop=2018-07-23&19:34:58granularity=300"))
> colnames(df1) <- c("time", "low", "high", "open", "close", "volume")
> df1$time <- anytime(df1$time)
> df1Sort <- df1[order(df1$time),]
> head(df1Sort, 5)
time low high open close volume
299 2018-07-23 16:13:00 7747.00 7747.01 7747.01 7747.01 9.2029168
298 2018-07-23 16:14:00 7743.17 7747.01 7747.00 7747.01 7.0205668
297 2018-07-23 16:15:00 7745.47 7745.73 7745.67 7745.73 0.9075707
296 2018-07-23 16:16:00 7745.72 7745.73 7745.72 7745.73 4.6715157
295 2018-07-23 16:17:00 7745.72 7745.73 7745.72 7745.72 2.4921921
> write_csv(df1Sort, "df1Sort.csv", col_names = TRUE)
> df2 <- read_csv("df1Sort.csv", col_names = TRUE)
Parsed with column specification:
cols(
time = col_datetime(format = ""),
low = col_double(),
high = col_double(),
open = col_double(),
close = col_double(),
volume = col_double()
)
> head(df2, 5)
# A tibble: 5 x 6
time low high open close volume
<dttm> <dbl> <dbl> <dbl> <dbl> <dbl>
1 2018-07-23 22:13:00 7747 7747 7747 7747 9.20
2 2018-07-23 22:14:00 7743 7747 7747 7747 7.02
3 2018-07-23 22:15:00 7745 7746 7746 7746 0.908
4 2018-07-23 22:16:00 7746 7746 7746 7746 4.67
5 2018-07-23 22:17:00 7746 7746 7746 7746 2.49
"Is there a program that can join POSIX variables across time zones... without having to convert them to the same time zone first?"
也许吧?但如果是这样,他们几乎可以肯定只是在幕后转换为 UTC 并且只是向您隐藏它。我不知道 R 中有这样的事情。(
data.table
是我所知道的唯一可以加入除完全相等之外的任何东西的包,而且它没有这个功能。)如果我是你,我只是将所有内容都转换为一个时区 - 可能是 UTC。阅读更多最佳实践
"Is it possible to prevent write_csv from changing POSIX variables to UTC?"
不是内置的。
?write_csv
文档非常清楚:它没有为此列出任何选项,而是说 "POSIXct's are formatted as ISO8601.""Is there a csv write function that doesn't change POSIX variables?"
当然,内置的
write.csv
不会更改为 UTC(我认为它使用系统设置),并且data.table::fwrite
提供了很多选项。如果您想控制日期的保存方式,我认为最好的办法是将它们转换为您想要的任何格式的character
,然后任何编写函数都应该可以很好地处理它们。您应该查看?data.table::fwrite
文档,它提供了很好的信息。他们警告说"write.csv"
选项可能会很慢。
您应该在问题中包含可重现的示例。这是一个:
t = as.POSIXct("2018-01-01 01:30:00", tz = "Africa/Addis_Ababa")
t
# [1] "2018-01-01 01:30:00 EAT"
d = data.frame(t)
library(readr)
write_csv(d, "tz_test.csv")
system("head tz_test.csv")
# 2017-12-31T22:30:00Z
library(data.table)
fwrite(d, "tz_test_dt.csv", dateTimeAs = "write.csv")
system("head tz_test_dt.csv")
# t
# 2018-01-01 01:30:00
write.csv(d, "tz_test_base.csv")
system("head tz_test_base.csv")
# "","t"
# "1",2018-01-01 01:30:00
您似乎在使用 tidyverse 中的库;你看过 lubridate 库了吗?
as_date() 的帮助文件可以帮助您在 append/join 数据之前将日期时间变量转换为所需的时区。
例如:
> dt_utc <- ymd_hms("2010-08-03 00:50:50")
> dt_utc
[1] "2010-08-03 00:50:50 UTC"
> as_datetime(dt_utc, tz = "Australia/Melbourne")
[1] "2010-08-03 10:50:50 AEST"