我有一个有点大的数据集(784,932行/项,27,492个唯一ID)。对于每个 ID 中的每个项,我正在尝试创建一个等于1的虚拟变量,如果日期之间的差异小于60秒。
程式化数据和代码:
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秒,所以假人是1.第二行和第三行也有共同的ID和Item,但是这里日期的差异远大于60秒,因此哑是0。
我设法获得了我想要的输出,但操作很慢。对于1000行,大约需要40秒(请参阅下面的system.time
结果)。这对应于约。整个数据集180分钟(我的计算机内存不足并在此之前很久就崩溃了)。
user system elapsed
36.485 3.328 39.800
如何更快地完成此操作?我可以使用data.table
完成相同的输出,是否更快?
答案 0 :(得分:7)
您可以按照建议使用data.table
。您需要将POSIXlt
转换为POSIXct
:
library(data.table)
df$Date <- as.POSIXct(df$Date)
DT <- as.data.table(df)
DT[, dummy_date := fnDummy(Date), by=c('ID', 'Item')]
但是,减速的很大一部分可能在ifelse
函数中,因为你创建了一个布尔值,所以你真的不需要它:
as.integer(c(FALSE, diff(date) < 60))
答案 1 :(得分:2)
您也可以使用dplyr来解决此问题:
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 = as.POSIXct(Date))
library(dplyr)
df %.%
group_by(ID, Item) %.%
mutate(
lagged = lag(Date, order_by = Date, default = 999),
dummy = Date - lagged < 60
)
lag()
有效地推广diff()
,允许您指定第一个元素的排序值和默认值。 (它目前也失去了向量的属性,但将在未来版本中修复。跟踪https://github.com/hadley/dplyr/issues/166处的进度)