如何防止write.csv将POSIXct、日期和时间类更改为字符/因子?

7

我有一个.csv文件,每个字段分别是日期时间、日期和时间。 原本它们都是字符型字段,我已经相应地进行了转换。 在我的代码末尾,如果我执行以下操作:

str(data)

我将获得

datetime: POSIXct
date: Date
time: Class 'times'  atomic [1:2820392] (....) attr(*, "format")= chr "h:m:s"

现在,我对此感到非常满意,并希望创建一个 .csv 文件,这是我的代码:

write.csv(data, file = "data.csv", row.names = FALSE)

我也尝试过

write.table(data, "data.csv", sep = ",", row.names = FALSE)

我使用两种方法都得到了相同的结果,即当编写新的 .csv 文件时,我的所有转换都会丢失:一切都变回字符。我怀疑在 write 函数中缺少某些参数,但我已经搜索了整个下午,仍然找不到答案。请问有人可以帮忙吗?
3个回答

7

如果您想保留所有时间信息,以便可以再次读取,请使用以下方法:

dat <- data.frame(time=as.POSIXlt("2013-04-25 09:00 BST"), quantity=1)
dat2 <- dat
dat2$time <- format(dat2$time, usetz=TRUE)
write.csv(dat2, "time.csv", row.names=FALSE)

它给出以下CSV文件:
"time","quantity"
"2013-04-25 09:00:00 BST",1

在这种情况下,时区信息明确呈现;如果您将write.csv应用于原始dat,则格式将丢失。


4
如果您使用了dplyrlubridate,您可以使用以下一行代码生成具有ISO8601日期格式(以便不会丢失任何信息)的CSV文件:write.csv(mutate(data, time=format(time, "%FT%H:%M:%S%z")), file="test.csv", row.names=FALSE)。您可以使用以下代码从该文件恢复数据框:df2 <- read.csv("test.csv") %>% mutate(time=ymd_hms(time))。请注意,此代码不改变原始意义,只是使内容更加通俗易懂。 - RubenLaguna
1
没有 dplyrlubridate 的话,代码将会是 data$time = format(data$time,format="%FT%H:%M:%S%z"); write.csv(data,"time.csv",row.names=FALSE) - bonna
@RubenLaguna 应该将其中一个发布为解决方案。我今天遇到了同样的问题,并使用了你的答案。 - Eric Krantz
@bonna 应该将其中一个作为解决方案发布。我今天遇到了同样的问题,使用了你的答案。 - Eric Krantz

4

根据 ?write.table 的说明:

数据框中任何列,如果是列表或有类别(例如日期),将会被适当的'as.character'方法转换:这些列默认不加引号。

简单说,你只能将文本/字符写入文本文件。如果想要保留二进制R表示形式的对象,请使用save


感谢您的回答,乔舒亚。我需要将我的文件读入ArcMap中,所以仅保存是不够的 - 至少根据我目前所了解的情况是这样。 然而,我发现.csv文件并不那么糟糕:如果格式正确,ArcMap会正确地将字符类型解释为日期、时间,甚至是日期时间 - 只要我在地理数据库中创建我的shapefiles即可。 - Catarina Aires

1
如果您愿意将dplyrlubridate添加为依赖项,就可以使用以下方式生成具有ISO8601日期(这样您就不会失去任何信息)的CSV:
#install.packages("tidyverse")
#install.packages("dplyr")
library(dplyr)
library(lubridate, warn.conflicts = FALSE)
dat <- data.frame(time=as.POSIXlt("2013-04-25 09:00 BST"), quantity=1) # example data
write.csv(mutate(dat, time=format(time, "%FT%H:%M:%S%z")), file="test.csv", row.names=FALSE)

这将生成一个CSV文件,其内容如下:
"time","quantity"
"2013-04-25T09:00:00+0200",1

正如你所看到的,CSV文件中包含ISO8601格式的日期和时区信息,因此不会丢失任何信息。

如果您想读取该CSV文件,可以这样做。

df2 <- read.csv("test.csv") %>% mutate(time=ymd_hms(time))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接