【发布时间】:2014-02-21 12:09:46
【问题描述】:
我有一个较大的数据集(784,932 行/项目,27,492 个唯一 ID)。对于每个 ID 中的每个 Item,如果日期之间的差异小于 60 秒,我会尝试创建一个等于 1 的虚拟变量。
风格化的数据和代码:
ID <- c(1,1,1,1,1,1,3,3,3,3,3,3)
Item <- c(10,10,10,20,20,20,10,20,10,10,10,20)
Date <- c("19/11/13 18:58:00","19/11/13 18:58:21","19/11/13 20:58:00","19/11/13 18:58:00","19/11/13 18:58:00","19/11/13 18:58:00","19/11/13 18:58:00","19/11/13 18:58:00","19/11/13 18:58:00","19/11/13 18:58:00","19/11/13 18:58:00","19/11/13 19:58:00")
df <- data.frame(ID, Item, Date)
df <- df[order(ID, Date), ]
df[, "Date"] = lapply(df["Date"],function(x){strptime(x, "%d/%m/%y %H:%M:%S")})
# less than 60 sec difference = 1 (first item set to 999 -> 0)
fnDummy <- function(date) { ifelse(c(999, diff(date))<60, 1, 0) }
library(plyr)
ddply(df, .(ID, Item), transform, Dummy=fnDummy(Date) )
输出:
ID Item Date Dummy
1 1 10 2013-11-19 18:58:00 0
2 1 10 2013-11-19 18:58:21 1
3 1 10 2013-11-19 20:58:00 0
4 1 20 2013-11-19 18:58:00 0
5 1 20 2013-11-19 18:58:00 1
6 1 20 2013-11-19 18:58:00 1
7 3 10 2013-11-19 18:58:00 0
8 3 10 2013-11-19 18:58:00 1
9 3 10 2013-11-19 18:58:00 1
10 3 10 2013-11-19 18:58:00 1
11 3 20 2013-11-19 18:58:00 0
12 3 20 2013-11-19 19:58:00 1
从输出中可以看出第一行和第二行有共同的ID和Item,而Date的差只有21秒,所以dummy是1。第二行和第三行也有共同的ID和Item,但是这里日期差远大于 60 秒,所以 dummy 为 0。
我设法得到了我想要的输出,但是操作很慢。对于 1000 行,大约需要 40 秒(参见下面的 system.time 结果)。这相当于大约。整个数据集需要 180 分钟(我的计算机内存不足并在此之前很久就崩溃了)。
user system elapsed
36.485 3.328 39.800
我怎样才能使这个操作更快?我可以使用data.table 完成相同的输出吗?它更快吗?
【问题讨论】:
-
你为什么使用
ifelse?c(FALSE, diff(date) < 60)应该足够了。如果您确实需要 0 和 1,请使用as.integer。 -
我知道你得到了答案,但我有点困惑。您问题中的代码甚至不适合我。我在
ddply行收到错误消息。
标签: r data.table subset plyr