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)]