【问题标题】:apply function to rolling window in panel data in R将函数应用于R中面板数据中的滚动窗口
【发布时间】:2014-05-11 14:24:40
【问题描述】:

我正在尝试在滚动窗口中按类别应用函数(例如标准偏差):

我有以下数据:

cat = c("A", "A", "A", "A", "B", "B", "B", "B") 
year = c(1990, 1991, 1992, 1993, 1990, 1991, 1992, 1993) 
value = c(2, 3, 5, 6, 8, 9, 4, 5) 
df = data.frame(cat, year, value)

我想创建一个新列(比如 sd),按 cat 估算两年窗口内的标准差。

这是我想到的结果:

关于如何实现这一点的任何建议?

【问题讨论】:

    标签: r time-series panel-data rollapply


    【解决方案1】:

    可以使用zoo 包中的rollapply 来完成:

    library(zoo)
    
    cat = c("A", "A", "A", "A", "B", "B", "B", "B") 
    year = c(1990, 1991, 1992, 1993, 1990, 1991, 1992, 1993) 
    value = c(2, 3, 5, 6, 8, 9, 4, 5) 
    df = data.frame(cat, year, value)
    
    df$stdev <- unlist(by(df, df$cat, function(x) {
      c(NA, rollapply(x$value, width=2, sd))
    }), use.names=FALSE)
    
    print(df)
    ##   cat year value     stdev
    ## 1   A 1990     2        NA
    ## 2   A 1991     3 0.7071068
    ## 3   A 1992     5 1.4142136
    ## 4   A 1993     6 0.7071068
    ## 5   B 1990     8        NA
    ## 6   B 1991     9 0.7071068
    ## 7   B 1992     4 3.5355339
    ## 8   B 1993     5 0.7071068
    

    如果您更愿意使用plyr 函数而不是by,也可以使用ddply

    df$stdev <- ddply(df, .(cat), summarise, 
                      stdev=c(NA, rollapply(value, width=2, sd)))$stdev
    

    作为一个云雀,我对上述两种方法以及@thelatemail在此答案下方的评论线程中指出的ave方法进行了system.time(多次)比较(以“新鲜”开头)数据框的副本)。

    df <- data.frame(cat, year, value)
    system.time(df$stdev <- with(df, ave(value, cat, FUN=function(x) c(NA, rollapply(x, width=2, sd)))))
    
    df <- data.frame(cat, year, value)
    system.time(df$stdev <- unlist(by(df, df$cat, function(x) c(NA, rollapply(x$value, width=2, sd))), use.names=FALSE))
    
    df <- data.frame(cat, year, value)
    system.time(df$stdev <- ddply(df, .(cat), summarise, stdev=c(NA, rollapply(value, width=2, sd)))$stdev)
    

    aveby 方法都采用:

       user  system elapsed 
      0.002   0.000   0.002 
    

    ddply 版本需要:

       user  system elapsed 
      0.004   0.000   0.004 
    

    并不是说速度真的是个问题,但看起来aveby 版本是最有效的方法。

    【讨论】:

    • 谢谢,但这不太正确 - 我希望将这些标准偏差按“猫”分组。我可以在这里使用 ddply 或类似的东西吗?
    • 不需要unlist(by(...)) - ave 可能更合适:with(df, ave(value, cat, FUN=function(x) c(NA, rollapply(x, width=2, sd)) ))
    • 不错。没想到aveinteraction(...); split(x, g) &lt;- lapply(split(x, g), FUN) 在幕后工作,所以它在幕后做了很多。
    • 使用rollapplyrfill=NA 参数可以稍微简化一下:ave(df$value, df$cat, FUN = function(v) rollapplyr(v, 2, sd, fill = NA))
    • @G 现在我想返回并将其添加到时间测试中!这可能是最好的全方位解决方案。
    猜你喜欢
    • 2013-10-25
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 2018-02-09
    • 2012-03-10
    • 1970-01-01
    • 2018-12-13
    • 1970-01-01
    相关资源
    最近更新 更多