R:如何快速地对子集的子集进行转换(优化或替代`ddply`)?

bon*_*nna 4 r subset plyr data.table

我有一个有点大的数据集(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) )
Run Code Online (Sandbox Code Playgroud)

输出:

   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
Run Code Online (Sandbox Code Playgroud)

从输出中你可以看到第一行和第二行有共同的ID和Item,而Date的差异只有21秒,所以虚拟是1.第二行和第三行也有共同的ID和Item,但这里的区别在于日期远大于60秒,因此哑是0.

我设法获得了我想要的输出,但操作很慢.1000行需要大约40秒(见system.time下面的结果).这对应于约.整个数据集180分钟(我的计算机内存不足并在此之前很久就崩溃了).

   user  system elapsed 
 36.485   3.328  39.800 
Run Code Online (Sandbox Code Playgroud)

如何更快地完成此操作?我可以使用相同的输出data.table,并且它更快吗?

Jus*_*tin 7

你可以data.table按照你的建议使用.你必须转换你的POSIXltPOSIXct:

library(data.table)
df$Date <- as.POSIXct(df$Date)
DT <- as.data.table(df)

DT[, dummy_date := fnDummy(Date), by=c('ID', 'Item')]
Run Code Online (Sandbox Code Playgroud)

然而,减速的很大一部分可能在ifelse函数中,你并不真正需要它,因为你正在创建一个布尔值:

as.integer(c(FALSE, diff(date) < 60))
Run Code Online (Sandbox Code Playgroud)