【问题标题】:Sum over rows (rollapply) with time decay对具有时间衰减的行求和(rollapply)
【发布时间】:2014-12-29 18:27:21
【问题描述】:

这是我之前发布的问题的后续问题(有关更多详细信息,请参阅Sum over rows with multiple changing conditions R data.table)。我想计算这 3 名受试者在过去 5 年中经历了多少次事件。所以一直在使用zoo 包中的rollapply 对滚动窗口求和。这假设 5 年前的经验与 1 年前的经验一样重要(相同的权重),所以现在我想为输入总和的经验包括一个时间衰减。这基本上意味着 5 年前的经验不会以与 1 年前的经验相同的权重进入总和。

在我的情况下,我想包括一个与年龄相关的衰减(即使对于其他应用程序来说更快或更慢的衰减,例如平方根或平方可能是可能的)。

例如,假设我有以下数据(为了清楚起见,我建立在以前的数据之上):

mydf <- data.frame (Year = c(2000, 2001, 2002, 2004, 2005,
                         2007, 2000, 2001, 2002, 2003,
                         2003, 2004, 2005, 2006, 2006, 2007),
                Name = c("Tom", "Tom", "Tom", "Fred", "Gill",
                         "Fred", "Gill", "Gill", "Tom", "Tom",
                         "Fred", "Fred", "Gill", "Fred", "Gill", "Gill"))

# Create an indicator for the experience 
mydf$Ind <- 1

# Load require packages
library(data.table)
library(zoo)

# Set data.table
setDT(mydf)
setkey(mydf, Name,Year)

# Perform cartesian join to calculate experience. I2 is the new experience indicator 
m <- mydf[CJ(unique(Name),seq(min(Year)-5, max(Year))),allow.cartesian=TRUE][,
        list(Ind = unique(Ind), I2 = sum(Ind,na.rm=TRUE)),
        keyby=list(Name,Year)]

# This is the approach I have been taking so far. Note that is a simple rolling sum of I2
m[,Exp := rollapply(I2, 5, function(x) sum(head(x,-1)), 
                align = 'right', fill=0),by=Name]

所以现在的问题是,我如何才能将与年龄相关的衰减纳入此计算。为了对此建模,我需要先将体验除以体验的年龄,然后再输入总和。

我一直在尝试使用以下方式使其工作:

 m[,Exp_age := rollapply(I2, 5, function(x) sum(head(x,-1)/(tail((Year))-head(Year,-1))), 
                     align = 'right', fill=0),by=Name]

但它不起作用。我认为我的主要问题是我无法正确计算体验的年龄,因此我可以除以总和中的年龄。结果应该类似于下面myres data.frame 中的Exp_age

myres <- data.frame(Name = c("Fred", "Fred", "Fred", "Fred", "Fred", 
                         "Gill", "Gill", "Gill", "Gill", "Gill", "Gill", 
                         "Tom", "Tom", "Tom", "Tom", "Tom"), 
                Year = c(2003, 2004, 2004, 2006, 2007, 2000, 2001, 2005,
                         2005, 2006, 2007, 2000, 2001, 2002, 2002, 2003), 
                Ind = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), 
                Exp = c(0, 1, 1, 3, 4, 0, 1, 1, 1, 2, 3, 0, 1, 2, 2, 4), 
                Exp_age = c(0, 1, 1, 1.333333333, 1.916666667, 0, 1, 0.45, 
                            0.45, 2.2, 2, 0, 1, 1.5, 1.5, 2.833333333))

任何指针将不胜感激!

【问题讨论】:

    标签: r time sum data.table rollapply


    【解决方案1】:

    如果我对您的理解正确,您正在尝试使用width=5 进行rollapply,而不是进行简单的求和,而是进行加权求和。权重是相对于 5 年窗口的经验年龄。我会这样做:首先在data.table 中设置键,使其按Name 正确递增顺序,然后您知道x 变量中的最后一项是最年轻的,第一项是最老的(你已经在你的代码中这样做了)。我不能完全说出你想要重量的方向(最年轻的体重最大或最年长的人),但你明白了:

    setkey(m, Name, Year)
    my_fun = function(x) { w = 1:length(x); sum(x*w)}
    m[,Exp_age:=rollapply(I2, width=5, by=1, fill=NA, FUN=my_fun, by.column=FALSE, align="right") ,by=Name]
    

    【讨论】:

    • 非常感谢您的快速回复。你是对的,这就是我试图实现的目标。我已经调整了函数以满足my_fun = function(x) {w = length(x):1; sum(x/w)} 的需求,这似乎返回了正确的值(或至少一些),但Exp_age 列未按预期对齐。另外,我收到 3 条警告消息:1: In ``[.data.table``(m, , ``:=``(Exp_age, rollapply(I2, width = 5, by = 1, : Supplied 9 items to be assigned to group 1 of size 13 in column 'Exp_age' (recycled leaving remainder of 4 items).(续下一条评论)
    • 2: In ``[.data.table``(m, , ``:=``(Exp_age, rollapply(I2, width = 5, by = 1, : Supplied 9 items to be assigned to group 2 of size 13 in column 'Exp_age' (recycled leaving remainder of 4 items). 3: In ``[.data.table``(m, , ``:=``(Exp_age, rollapply(I2, width = 5, by = 1, : Supplied 9 items to be assigned to group 3 of size 13 in column 'Exp_age' (recycled leaving remainder of 4 items). 有什么想法吗?
    • 我想我发现了问题所在。我必须允许partial = TRUE。所以代码是:m[,Exp_age:=rollapply(I2, width=5, by=1, FUN=my_fun, by.column=FALSE, align="right", partial = TRUE), by=Name]。然后,我只需要滞后经验变量即可获得所需的结果(但我无法一口气完成)。
    • 你需要的是fill = NA,而不是partial=T。这将确保返回的向量与原始data.table 的长度相同。我编辑了我的答案
    猜你喜欢
    • 2022-09-23
    • 2011-11-28
    • 2021-04-21
    • 1970-01-01
    • 2015-06-18
    • 1970-01-01
    • 1970-01-01
    • 2021-07-17
    • 2012-01-28
    相关资源
    最近更新 更多