[英]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)
真正的全表有一千多个变量和一百万个个体。 这就是为什么我想用一种快速的方式来做事。
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>
自从6个月前提出这个问题以来, fwrite
已经改进并发布到CRAN。 我相信它现在应该像你想要的那样工作; 即快速、直接和方便的日期格式。 它现在具有dateTimeAs
参数,如下所示,从fwrite
的v1.10.0 手册页复制,就像现在在 CRAN 上一样。 随着时间的推移,请查看手册页的最新版本。
====
dateTimeAs
:Date/IDate、ITime 和 POSIXct 项的写入方式。
“ISO”(默认) - 2016-09-12
、 18:12:16
和2016-09-12T18:12:16.999999Z
。 为方便起见,无论是否有任何 R 选项(例如digits.secs),都会打印 0、3 或 6 位秒的小数位数。 这个想法是,如果存在毫秒和微秒,那么您很可能希望保留它们。 R 的内部 UTC 表示忠实地编写以鼓励 ISO 标准、阻碍时区歧义和速度。 要考虑的一种选择是在 UTC 时区中启动 R,只需在 shell 中使用“$ TZ='UTC' R”(注意:它必须在 TZ='UTC' 和 R 之间有一个或多个空格,其他任何内容都将被静默忽略;此 TZ 设置仅适用于该 R 进程)或 Sys.setenv(TZ='UTC') 在 R 提示符下,然后继续就像 UTC 是本地时间一样。
“壁球” - 20160912
、 181216
和20160912181216999
。 此选项允许使用整数 div 和 mod 操作快速简单地提取 yyyy、mm、dd 和(最常见的分组依据)yyyymm 部分。 例如,在 R 中,一行辅助函数可以分别使用 %/%10000、%/%100%%100、%%100 和 %/%100。 POSIXct UTC 被压缩为 17 位(始终包括 3 位毫秒,即使是 000),可以轻松地将其读取为 integer64(由 fread() 自动)。
“纪元” - 17056
、 65536
和1473703936.999999
。 自相关纪元(分别为 1970-01-01、00:00:00 和 1970-01-01T00:00:00Z)以来的基本天数或秒数,在此之前为负数(参见 ?Date)。 如果存在,则打印 0、3 或 6 位小数秒。
“write.csv” - 目前仅影响 POSIXct。 它是通过使用 as.character 方法编写的 write.csv,该方法关注digits.secs 并将R 的内部UTC 表示转换回该历史日期的本地时间(或“tzone”属性)。 因此,这可能很慢。 所有其他列类型(包括独立于时区的日期、IDate 和 ITime)都使用已经与 write.csv 一致的快速 C 代码编写为“ISO”选项。
由于新的专用 C 代码,前三个选项很快。 纪元到日期部分的转换使用 Howard Hinnant(参见参考资料)的快速方法,使用从 3 月 1 日开始的一年中的某一天。 您应该不会注意到这三个选项之间的写入速度有任何差异。 Date 和 IDate 支持的日期范围是 [0000-03-01, 9999-12-31]。 这 3,652,365 个日期中的每一个都经过了测试并与基础 R 进行了比较,包括该范围内的所有 2,790 个闰日。 此选项也适用于列表列单元格中的日期/时间向量。 不支持完全灵活的格式字符串(例如“%m/%d/%Y”)。 这是为了鼓励使用 ISO 标准,因为不知道如何在 C 级别快速实现这种灵活性。 如果需要,我们可能能够支持一两个更具体的选项。
====
我也遇到了同样的问题,我只是在写入之前将日期列更改为as.character,然后在阅读后将其更改回as.Date。 我不知道它如何影响读写时间,但对我来说这是一个足够好的解决方案。
这些数字有意义:) 似乎 fwrite 将数据格式更改为“Matlab 编码”,其中来源为“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》
由于似乎没有简单的解决方案,我正在尝试存储列类并再次将它们更改回来。
我取原始数据集 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 的向量来写
您需要添加参数:dateTimeAs = "ISO"。 通过添加参数 dateTimeAs = 并指定适当的选项,您将获得以所需格式和各自时区写入 csv 文件的日期。 这在处理与时区相关的 POSIXct 变量的情况下尤为重要。 缺少此参数可能会通过根据时区之间的小时差移动日期和时间来影响写入 csv 文件的时间戳。 因此,日期/时间变量 POSIXct,您需要添加: dateTimeAs = "write.csv" ; 不幸的是,这个选项可能很慢( https://www.rdocumentation.org/packages/data.table/versions/1.10.0/topics/fwrite? )。 祝你好运!!!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.