使用data.table包处理日期数据

11

我最近发现了data.table包,现在想知道是否应该替换掉我的一些plyr代码。总的来说,我真的很喜欢plyr,而且我基本上实现了我想要的一切。然而,我的代码运行时间比较长,加速的前景足以让我进行一些测试。但是这些测试很快就结束了,原因如下。

我经常使用plyr按包含日期的列对数据进行拆分并进行一些计算:

library(plyr)
DF <-  data.frame(Date=rep(c(Sys.time(), Sys.time() + 60), each=6), y=c(rnorm(6, 1), rnorm(6, -1)))
#Split up data and apply arbitrary function
ddply(DF, .(Date), function(df){mean(df$y) - df[nrow(df), "y"]})

然而,在data.table中使用日期格式的列似乎不起作用:

library(data.table)
DT <- data.table(Date=rep(c(Sys.time(), Sys.time() + 60), each=6), y=c(rnorm(6, 1), rnorm(6, -1)))
setkey(DT, Date)
#Error in setkey(DT, Date) : Column 'Date' cannot be auto converted to integer without losing information.

如果我理解这个包正确的话,只有在使用setkey()时才能获得实质性的加速。此外,我认为在日期和数字之间不断转换并不是好的编程习惯。所以,我是否有什么遗漏或者没有简单的方法可以用data.table实现这个功能呢?

sessionInfo()
R version 2.13.1 (2011-07-08)
Platform: x86_64-pc-mingw32/x64 (64-bit)

locale:
[1] C

attached base packages:
[1] grid      stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] data.table_1.6.3 zoo_1.7-2        lubridate_0.2.5  ggplot2_0.8.9    proto_0.3-9.2    reshape_0.8.4   
[7] reshape2_1.1     xtable_1.5-6     plyr_1.5.2      

loaded via a namespace (and not attached):
[1] digest_0.5.0    lattice_0.19-30 stringr_0.5     tools_2.13.1 

1
我没有使用过data.table,但请注意Sys.time()返回的是POSIXct日期时间值,而不是Date。特别地,返回的值(自1970年1月1日以来经过的秒数)通常不是整数值,因此将其转换为整数确实会丢失信息,就像错误消息所说的那样。 - Hong Ooi
1
请注意,即使您不使用setkey,data.table也可以显著提高执行时间。 - Andrie
1个回答

8
这应该可以使用:

DT <- data.table(Date=as.ITime(rep(c(Sys.time(), Sys.time() + 60), each=6)),
                 y=c(rnorm(6, 1), rnorm(6, -1)))
setkey(DT, Date)

The data.table包含一些带有整数存储模式的日期/时间类。请参阅?IDateTime:
日期和时间类使用整数存储以便于快速排序和分组。仍在实验阶段!
- IDate是从Date派生的一个日期类。它与Date类具有相同的内部表示形式,除了存储模式为整数。 - ITime是一种在一天中以整数秒数存储的时刻类。as.ITime不允许超过24小时的日期 。因为ITime以秒为单位存储,所以可以将其添加到POSIXct对象中,但不应将其添加到Date对象中。 - IDateTime需要输入日期时间并返回具有日期和时间列的数据表。

谢谢,这很有帮助。我实际上正在使用lubridate,它与ggplot2非常配合。由于这三个包(lubridate、ggplot2、plyr)都来自同一作者,并且在组合使用时非常好用,所以我想我会继续使用它们而不是转换。但是你的答案提供了一个很好的解决方法,当我有时间时,我想我会尝试一下使用data.table来测试速度改进。再次感谢! - Christoph_J

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