【问题标题】:cast string directly to IDateTime将字符串直接转换为 IDateTime
【发布时间】:2012-12-27 14:37:21
【问题描述】:

我正在使用data.table 的新版本,尤其是AWESOME fread 功能。我的文件包含作为字符串加载的日期(因为我不知道该怎么做)看起来像01APR2008:09:00:00

我需要在这些日期时间对 data.table 进行排序,然后以IDateTime 格式(或其他我还不知道的格式)进行有效排序。

> strptime("01APR2008:09:00:00","%d%b%Y:%H:%M:%S")
[1] "2008-04-01 09:00:00"

> IDateTime(strptime("01APR2008:09:00:00","%d%b%Y:%H:%M:%S"))
        idate    itime
1: 2008-04-01 09:00:00

> IDateTime("01APR2008:09:00:00","%d%b%Y:%H:%M:%S")
Error in charToDate(x) : 
character string is not in a standard unambiguous format 

看来我做不到DT[ , newType := IDateTime(strptime(oldType, "%d%b%Y:%H:%M:%S"))]

那么我的问题是:

  1. 有没有办法从fread 直接转换为IDateTime,这样我以后可以高效地排序?
  2. 如果没有,知道我希望能够按此日期时间列对 DT 进行排序的最有效方法是什么

【问题讨论】:

  • 你能展示它们看起来你的数据文件吗?
  • 您好,该文件是一个带有sep=";" 的csv 文件,日期格式类似于"01APR2008:09:00:00",即format="%d%b%Y:%H:%M:%S"。我所做的是DT[,date:=IDate(oldType,"%d%b%Y")];DT[,time:=ITime(oldType,"%d%b%Y:%H:%M:%S")],最后是setkeyv(DT,c("date","time"))
  • 日期是你数据的第一列吗?

标签: r datetime data.table


【解决方案1】:

不幸的是(为了提高效率)strptime 产生了一个 POSIXlt 类型,data.table 不支持这种类型,并且总是由于它的大小(每个日期 40 个字节!)和结构。尽管strftime 产生了更好的POSIXct,但它仍然通过POSIXlt 来实现。更多信息在这里:

http://stackoverflow.com/a/12788992/403310

寻找诸如as.Date之类的基本函数,它也使用strptime,从存储为双精度的纪元(奇怪地)创建一个整数偏移量。 data.table 中的 IDate(和朋友)类旨在实现整数时代偏移量存储为,嗯,整数。适合base::sort.list(method = "radix")的快速排序(真的是计数排序)。 IDate 的目标并不是快速(通常是一次性)转换。

因此,为了正确或错误地转换字符串日期/时间,我倾向于使用自己的辅助函数。

如果字符串日期是"2012-12-24",我倾向于:as.integer(gsub("-", "", col)) 并继续使用YYYYMMDD 整数日期。同样,时间可以是HHMMDD 作为整数。两列:datetime 如果您通常希望在一天内而不是前一天,则单独使用 roll = TRUE。按月分组简单快捷:by = date %/% 100L。添加和减去天数很麻烦,但无论如何您都不想添加日历日,而是添加工作日或工作日。所以无论如何,这都是对您的工作日向量的查找。

在您的情况下,字符月份需要转换为 1:12。您的日期“01APR2008”中没有分隔符,因此 substring 将是一种方式,然后是月份名称上的 matchfmatch。您可以控制文件格式吗?如果是这样,数字最好采用自然排序的明确格式,例如 %Y-%m-%d%Y%m%d

我还没有知道如何在fread 中最好地做到这一点,因此日期/时间目前保留为字符,因为我还不确定如何检测日期格式或输出哪种类型。它确实需要输出整数或双日期,而不是低效的字符。我怀疑我对YYYYMMDD 整数的使用被视为非常规,所以我有点犹豫是否将其设为默认值。它们有自己的位置,基于纪元的日期也有优缺点。我建议的只是日期必须始终基于纪元。

你怎么看?顺便说一句,感谢fread 的鼓励;很高兴看到。

【讨论】:

  • 嘿 Matthew 感谢您的回答,我想一种可能性是允许 colClasses 参数,如 read.csv 中的。毕竟,您可以在R) setAs("character","myDate", function(from) as.Date(from, format="%d/%m/%y") )R) system.time(data <- read.csv(file=filePath, sep=";", stringsAsFactors=TRUE, colClasses=c("factor","factor","numeric","myDate"), nrows=10));
  • 此外,如果您可以在包中添加微秒分辨率时间,我认为您会接触更多人。所有的 HFTraders/quants 都在玩这些东西......(可以说他们不应该为此使用 R,但我们不要去那里)
  • 同意,colClasses 已经在要添加的列表中(TO DO 列表位于 fread.c 的顶部),但作为命名向量允许覆盖特定列而不需要指定它们全部。这实际上是一个关于默认值的问题。我想POSIXct,那么。这已经支持微秒,所以我认为没有什么特别的data.table 需要真正支持iiuc(除了 fread 可以直接快速加载它们)。不过,我想做 fread 的主要原因是双分隔文件 (sep2),例如在基因组学中。
【解决方案2】:

我不知道您的文件结构如何,但从您的评论中您想使用日期字段作为键。为什么不将其作为时间序列阅读并在阅读时对其进行格式化?

这里我用zoo来做。(这里我假设日期列是第一个,否则见index.colum参数)

ff <- function(x) as.POSIXct(strptime(x,"%d%b%Y:%H:%M:%S"))

h <- read.zoo(text = "03avril2008:09:00:00  125
                      02avril2008:09:30:00  126
                      05avril2008:09:10:00  127
                      04avril2008:09:20:00  128
                      01avril2008:09:00:00  128"
                      ,FUN=ff)

您可以按照正确的格式对日期进行排序。

从 POSIXct 到 IDateTime 的转换很自然

    IDateTime(index(h))
        idate    itime
1: 2008-04-01 09:00:00
2: 2008-04-02 09:30:00
3: 2008-04-03 09:00:00
4: 2008-04-04 09:20:00
5: 2008-04-05 09:10:00

这里肯定你还是做2次转换,但是你是在读取数据的时候做的,第二次你做的时候没有处理任何格式问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-11
    • 2015-12-12
    • 2015-02-25
    • 1970-01-01
    • 2021-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多