【问题标题】:R: data.table. How to save dates properly with fwrite?R:数据表。如何使用 fwrite 正确保存日期?
【发布时间】:2016-11-17 15:57:21
【问题描述】:

我有一个数据集。我可以选择从 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>

【问题讨论】:

  • 我可以知道为什么投反对票吗?
  • 您能否在您的问题 (head(yourData)) 中将一小部分数据放在这里?人们访问将更容易、更合法。另外,日期是否存储为字符串?
  • 可能是因为粗略的 zippyshare 东西。作为参考,这是你的 FR 和 github.com/Rdatatable/data.table/issues/1772 包就它“没有意义”而言,你知道它的意义,因为它在链接中向你解释过......就我个人而言,我有一个 write_dates(DT, patt) 函数将所有符合patt 模式的日期列转换为具有我所需格式的字符串。所以我做library(magrittr); fwrite(copy(DT) %&gt;% write_dates("date$"), file = "DT.csv")
  • 我对 zippyshare 投了反对票。选择一个不会试图劫持浏览器会话的公共存储库。
  • @skan 我会使用dput,它不需要验证码,速度非常快,不需要任何第三方主机。

标签: r date datetime data.table posixct


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    自从 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 标准、阻止时区模糊和速度。要考虑的一种选择是在 UTC 时区中启动 R,只需在 shell 中使用“$ TZ='UTC' R”(注意:它必须是 TZ='UTC' 和 R 之间的一个或多个空格,其他任何内容都将被静默忽略;此 TZ 设置仅适用于该 R 进程)或 R 提示符下的 Sys.setenv(TZ='UTC'),然后像 UTC 是本地时间一样继续。

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

    • “纪元” - 17056655361473703936.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”属性)。因此,这可能很慢。所有其他列类型(包括与时区无关的 Date、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 级快速实现这种灵活性。如果需要,我们可能会支持一两个更具体的选项。

    ====

    【讨论】:

    • 您能否添加对nanotime 的支持,它可以很好地保存其底层integer64,但需要重新分类。
    • @DirkEddelbuettel 会的。感谢#1982 - 添加到下一个里程碑。
    • 如何将“ISO”转换回 POSIXct? as.POSIXct(DT$Time, format = "%Y-%m-%dT%H:%M:%SZ") ?
    【解决方案3】:

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

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

    例如

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

    [1]“1967-08-06”

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

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

        我取原始数据集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的向量

        【讨论】:

          猜你喜欢
          • 2011-12-25
          • 1970-01-01
          • 1970-01-01
          • 2019-10-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多