R 在最后365天窗口内执行运行总计的有效方法
这就是我的数据框的外观: 库(数据表)R 在最后365天窗口内执行运行总计的有效方法,r,vectorization,dplyr,zoo,rollapply,R,Vectorization,Dplyr,Zoo,Rollapply,这就是我的数据框的外观: 库(数据表) df% 突变(day=EventDate-EventDate[1]) f=0& df$day[i]-df$day尝试一下: DF <- read.table(text = "Name EventType EventDate SalesAmount RunningTotal Runningtotal(prior365Days) John Email 1/1/2014 0 0 0 J
df%
突变(day=EventDate-EventDate[1])
f=0&
df$day[i]-df$day尝试一下:
DF <- read.table(text = "Name EventType EventDate SalesAmount RunningTotal Runningtotal(prior365Days)
John Email 1/1/2014 0 0 0
John Sale 2/1/2014 10 10 10
John Sale 7/1/2014 20 30 30
John Sale 4/1/2015 30 60 50
John Webinar 5/1/2015 0 60 50
Tom Email 1/1/2014 0 0 0
Tom Sale 2/1/2014 15 15 15
Tom Sale 7/1/2014 10 25 25
Tom Sale 4/1/2015 25 50 35
Tom Webinar 5/1/2015 0 50 35", header = TRUE)
fun <- function(x, date, thresh) {
D <- as.matrix(dist(date)) #distance matrix between dates
D <- D <= thresh
D[lower.tri(D)] <- FALSE #don't sum to future
R <- D * x #FALSE is treated as 0
colSums(R)
}
library(data.table)
setDT(DF)
DF[, EventDate := as.Date(EventDate, format = "%m/%d/%Y")]
setkey(DF, Name, EventDate)
DF[, RT365 := fun(SalesAmount, EventDate, 365), by = Name]
# Name EventType EventDate SalesAmount RunningTotal Runningtotal.prior365Days. RT365
# 1: John Email 2014-01-01 0 0 0 0
# 2: John Sale 2014-02-01 10 10 10 10
# 3: John Sale 2014-07-01 20 30 30 30
# 4: John Sale 2015-04-01 30 60 50 50
# 5: John Webinar 2015-05-01 0 60 50 50
# 6: Tom Email 2014-01-01 0 0 0 0
# 7: Tom Sale 2014-02-01 15 15 15 15
# 8: Tom Sale 2014-07-01 10 25 25 25
# 9: Tom Sale 2015-04-01 25 50 35 35
#10: Tom Webinar 2015-05-01 0 50 35 35
DF以下是一种使用数据中的foverlaps
函数的方法。表
包:
require(data.table)
setDT(df)[, end := as.Date(EventDate, format="%d/%m/%Y")
][, start := end - 365L]
setkey(df, Name, start, end)
olaps = foverlaps(df, df, nomatch=0L, which=TRUE)
olaps = olaps[xid >= yid, .(ans = sum(dt$SalesAmount[yid])), by=xid]
df[olaps$xid, Runningtotal := olaps$ans]
如有必要,您可以通过以下操作删除开始
和结束
列:
df[, c("start", "end") := NULL]
很高兴知道它有多快/慢。使用data.table中较新的非等联接功能:
df1 = df[.(iName=Name,start = Date - 365L, end = Date),
on=.(Name=iName,Date >= start, Date <= end),nomatch = 0, allow.cart=TRUE][,
.(MyTotal = sum(SalesAmount)), by=.(Name,Date = Date.1)]
df[df1, on = .(Name,Date)]
df1=df[(iName=Name,start=Date-365L,end=Date),
on=。(Name=iName,Date>=开始,Date我想知道你是否尝试过实现@DavidArenburg的一些东西嗨,大卫,我实现了你的解决方案(从链接)到另一个问题。在过去365天窗口中,给定名称的累计运行总数是一个完全不同的问题。是的,我的意思是,我想知道您是否尝试修改它以解决新问题。这可能是到目前为止最快的解决方案far@DavidArenburg谢谢大卫,我从来没有想过。我想知道会是什么在本例中,他提供了两个临时数据集,我可以稍后加入。非常感谢您的帮助!我觉得您接受答案的速度非常快。30秒的运行时间非常好,但还有一个Rcpproll包;熟悉其(可能更快)方法的人现在可能不愿意回答。(不是我,我只是通过谷歌搜索找到的。)这对150万行行可行吗?@ExperimenteR 1.5MM是一个非常小的数据集。任何矢量化的代码都可以轻松处理。我所说的“矢量化”并不是指“矢量化”函数。@DavidArenburg D@DavidArenburg非常感谢!这就像魔术师罗兰一样,只花了不到30秒的时间。你们中的一位能解释一下为什么我使用的初始解决方案如此缓慢吗?@实验者该函数显然不适合很长的输入向量。但是,如果在数据集中,每个用户的时间序列都比几年长,销售频率通常比每天低得多。速度非常快。我只花了不到45秒的时间。谢谢你,阿伦。但是,我正在努力扩展解决方案以解决一个小问题。假设我还有一个专栏名为Fund。它有Fund a和B,只有在EventType==销售。例如,如果我只想要基金A的累计金额,我如何修改罗兰的解决方案或您的解决方案?1.您能否提供指向更大数据的链接(如果您无法共享,您能否生成具有类似设置的人工数据)?2.你在挣扎什么扩展?请用这个编辑你的帖子,并显示所需的输出(或者更好,作为一个新帖子,因为它似乎不同于此Q)。你能分享更大的数据吗?我想看看是否有任何可能的改进。@Frank我从Frank那里得到了解决方案。非常感谢你们。@gibbz00,Arun的解决方案(根据您的要求少于45秒)比我的解决方案慢(根据您的要求少于30秒)?您能否提供准确的时间(使用system.time
)?您能否告诉我们您的数据中有多少个唯一的名称?
df[, c("start", "end") := NULL]
df1 = df[.(iName=Name,start = Date - 365L, end = Date),
on=.(Name=iName,Date >= start, Date <= end),nomatch = 0, allow.cart=TRUE][,
.(MyTotal = sum(SalesAmount)), by=.(Name,Date = Date.1)]
df[df1, on = .(Name,Date)]