答:data.table。如何使用 fwrite 正确保存日期?

R: data.table. How to save dates properly with fwrite?

我有一个数据集。我可以选择从 Stata 文件或 SPSS 文件将其加载到 R 上。
在这两种情况下,它都正确加载了 haven 包。 日期被正确识别。

但是当我使用 data.table 的 fwrite 函数将它保存到磁盘时。
fwrite(ppp, "ppp.csv", sep=",", col.names = TRUE)

我有一个问题,日期消失并转换为不同的数字。例如,日期 1967-08-06 在 csv 文件中保存为 -879

我也试过使用 fwrite 选项,例如 quote=FALSE,但没有成功。

我上传了一小部分文件、spss、stata 和保存的 csv。

这是代码,是为了让您更轻松。

library(haven)
library(data.table)
ppp <- read_sav("pspss.sav") # choose one of these two.
ppp <- read_dta("pstata.dta")  # choose one of these two.
fwrite(ppp, "ppp.csv",  sep=",", col.names = TRUE) 

真正的整体table有一千多个变量,一百万个人。这就是为什么我想用一种快速的方式来做事。

http://www73.zippyshare.com/v/OwzwbyQq/file.html

这是给@ArtificialBreeze 的:

> head(my)
# A tibble: 6 x 9
  ID_2006_2011              TIS FECHA_NAC_2006    año2006 Edad_31_12_2006 SEXO_2006
         <dbl>            <chr>         <date>     <date>           <dbl>     <chr>
1  1.60701e+11 BBNR670806504015     1967-08-06 2006-12-31              39         M
2  1.60701e+11 BCBD580954916014     1958-09-14 2006-12-31              48         F
3  1.60701e+11 BCBL451245916015     1945-12-05 2006-12-31              61         F
4  1.60701e+11 BCGR610904916012     1961-09-04 2006-12-31              45         M
5  1.60701e+11 BCMR580148916015     1958-01-08 2006-12-31              48         F
6  1.60701e+11 BCMX530356917018     1953-03-16 2006-12-31              53         F
# ... with 3 more variables: PAIS_NAC_2006 <dbl>, FECHA_ALTA_TIS_2006 <date>,
#   FECHA_ALTA_TIS_2006n <date>

由于似乎没有简单的解决方案,我正在尝试存储列 类 并再次将它们改回来。

我取原始数据集ppp,

areDates <- (sapply(ppp, class) == "Date")

我把它保存在一个文件里,下次可以看。

ppp <- fread("ppp.csv", encoding="UTF-8")

现在我将新读取的数据集的 类 改回原来的数据集。

ppp[,names(ppp)[areDates] := lapply(.SD,as.Date),
 .SDcols = areDates ]

也许有人可以用 for 循环和命令集写得更好。

 ppp[,lapply(.SD, setattr, "class", "Date") , 
.SDcols = areDates]

也可以写成位置而不是TRUE和FALSE的向量

我也遇到了同样的问题,只是写之前把日期栏改成as.character,读完又改回as.Date。我不知道它如何影响读写时间,但这对我来说是一个足够好的解决方案。

这些数字有意义 :) 似乎 fwrite 将数据格式更改为 "Matlab coding",其中来源为“1970-01-01”。 如果您阅读数据,您可以使用这些代码将数字简单地更改为日期:

my$FECHA_NAC_2006<-as.Date(as.numeric(my$FECHA_NAC_2006),origin="1970-01-01")

例如

as.Date(-879,origin="1970-01-01")

[1]“1967-08-06”

自从 6 个月前提出这个问题后,fwrite 已经改进并发布到 CRAN。我相信它现在应该可以正常工作了;即快速、直接和方便的日期格式。它现在有如下 dateTimeAs 参数,从 fwrite's manual page 复制到 v1.10.0,就像现在在 CRAN 上一样。随着时间的推移,请查看最新版本的手册页。

====

dateTimeAs : Date/IDate、ITime 和 POSIXct 项目的写入方式。

  • "ISO"(默认) - 2016-09-1218:12:162016-09-12T18:12:16.999999Z。 0、3 或 6 位小数秒会在出现时为方便起见而打印,而不管任何 R 选项,例如 digits.secs。这个想法是,如果存在毫秒和微秒,那么您很可能希望保留它们。 R 的内部 UTC 表示被忠实地编写以鼓励 ISO 标准、阻止时区歧义和速度。要考虑的一个选项是在 shell 处简单地使用 "$ TZ='UTC' R" 在 UTC 时区启动 R(注意:TZ='UTC' 之间必须有一个或多个空格和 R,其他任何内容都将被默默忽略;此 TZ 设置仅适用于该 R 进程)或 Sys.setenv(TZ='UTC') 在 R 提示符下,然后继续,就好像 UTC 是本地时间一样。

  • "squash" - 2016091218121620160912181216999。此选项允许使用整数 div 和 mod 操作快速简单地提取 yyyy、mm、dd 和(最常见的分组依据)yyyymm 部分。例如,在 R 中,一行辅助函数可以分别使用 %/%10000、%/%100%%100、%%100 和 %/%100。 POSIXct UTC 被压缩为 17 位数字(始终包括 3 位毫秒数,即使是 000),可以舒适地读取为 integer64(由 fread() 自动读取)。

  • "epoch" - 17056655361473703936.999999。自相关纪元(分别为 1970-01-01,00:00:00 和 1970-01-01T00:00:00Z)以来的基本天数或秒数,在此之前为负数(参见 ?Date)。如果存在,则打印 0、3 或 6 位小数秒。

  • "write.csv" - 这目前只影响 POSIXct。它被写成 write.csv 通过使用 as.character 方法来编写,该方法注意 digits.secs 并将 R 的内部 UTC 表示转换回本地时间(或 "tzone" 属性)历史日期。因此,这可能很慢。所有其他列类型(包括独立于时区的 Date、IDate 和 ITime)都使用已经与 write.csv.

    [=52 一致的快速 C 代码编写为 "ISO" 选项=]

由于新的专用 C 代码,前三个选项速度很快。从 3 月 1 日开始,date-part 转换的纪元使用了 Howard Hinnant(请参阅参考资料)使用 day-of-year 的快速方法。您应该不会注意到这三个选项之间的写入速度有任何差异。 Date 和 IDate 支持的日期范围是 [0000-03-01, 9999-12-31]。这 3,652,365 个日期中的每一个都经过测试,并与基准 R 进行了比较,包括该范围内的所有 2,790 个闰日。此选项也适用于列表列单元格中 date/time 的向量。不支持完全灵活的格式字符串(例如“%m/%d/%Y”)。这是为了鼓励使用 ISO 标准,因为不知道如何在 C 级别上快速实现这种灵活性。如果需要,我们可能能够支持一两个更具体的选项。

====

您需要添加参数:dateTimeAs = "ISO"。 通过添加参数 dateTimeAs = 并指定适当的选项,您将在 csv 文件中获得具有所需格式和各自时区的日期。 这在处理与时区相关的 POSIXct 变量时尤为重要。缺少此参数可能会根据时区之间的小时差改变日期和时间,从而影响写入 csv 文件的时间戳。因此,date/time 变量 POSIXct,您需要添加: dateTimeAs = "write.csv" ;不幸的是,这个选项可能很慢 (https://www.rdocumentation.org/packages/data.table/versions/1.10.0/topics/fwrite?)。祝你好运!!!