【发布时间】:2016-03-31 01:56:00
【问题描述】:
我有一个大数据框(3M+ 行)。我正在尝试计算某个 ActivityType 在 21 天窗口中出现的次数。我从Rolling Sum by Another Variable in R 模拟了我的解决方案。但是仅仅一个ActivityType就需要很长时间。我不认为 3M+ 行会花费过多的时间。以下是我尝试过的:
dt <- read.table(text='
Name ActivityType ActivityDate
John Email 1/1/2014
John Email 1/3/2014
John Webinar 1/5/2014
John Webinar 1/20/2014
John Webinar 3/25/2014
John Email 4/1/2014
John Email 4/20/2014
Tom Email 1/1/2014
Tom Webinar 1/5/2014
Tom Webinar 1/20/2014
Tom Webinar 3/25/2014
Tom Email 4/1/2014
Tom Email 4/20/2014
', header=T, row.names = NULL)
library(data.table)
library(reshape2)
dt$ActivityType <- factor(dt$ActivityType)
dt$ActivityDate <- as.Date(dt$ActivityDate, "%m/%d/%Y")
dt <- dt[order(dt$Name, dt$ActivityDate),]
dt <- dcast(dt, Name + ActivityDate ~ ActivityType, fun.aggregate=length)
setDT(dt)
#Build reference table
Ref <- dt[,list(Compare_Value=list(I(Email)),Compare_Date=list(I(ActivityDate))), by=c("Name")]
#Use mapply to get last 21 days of value by Name
dt[,Email_RollingSum := mapply(ActivityDate=ActivityDate,Name=Name, function(ActivityDate, Name) {
d <- as.numeric(Ref$Compare_Date[[Name]] - ActivityDate)
sum((d <= 0 & d >= -21)*Ref$Compare_Value[[Name]])})]
这仅适用于 ActivityType=Email,然后我必须对其他 ActivityType 级别执行相同操作。我从中获得解决方案的链接谈到使用“mcapply”而不是“mapply”。请让我知道如何使用 mcapply 或任何其他可以使其更快的解决方案。
以下是预期的输出。对于每一行,我取 ActivityDate 和之前的 21 天,这 21 天是我的时间窗口。我一直在计算 ActivityType="Email" 出现在那个时间窗口中的时间。
Name ActivityType ActivityDate Email_RollingSum
John Email 1/1/2014 1
John Email 1/3/2014 2
John Webinar 1/5/2014 2
John Webinar 1/20/2014 2
John Webinar 3/25/2014 0
John Email 4/1/2014 1
John Email 4/20/2014 2
Tom Email 1/1/2014 1
Tom Webinar 1/5/2014 1
Tom Webinar 1/20/2014 1
Tom Webinar 3/25/2014 0
Tom Email 4/1/2014 1
Tom Email 4/20/2014 2
【问题讨论】:
-
在处理数百万行时,我经常将日期转换为数字。 as.numeric(dt$ActivityDate)。不是解决方案,但也许是一种改进。
-
由于 OP 明确说明了速度,因此最好根据您使用各种方法获得的时间来更新它。
-
WaltS 的方法耗时 1.89 小时。出于某种原因,我在尝试 eddi 的方法时两次内存不足。当 excel 使我的计算机崩溃时,Khasana 的方法正在运行(超过 2 小时)。
标签: r data.table dplyr zoo