【问题标题】:Collapse a string over a moving average window在移动平均窗口上折叠字符串
【发布时间】:2017-04-03 17:29:41
【问题描述】:

我正在计算一个向量在 3 个月的窗口内的移动平均值。我想在下面的数据框中添加另一列,在窗口中折叠月份。所以在下面的例子中:

library(lubridate)

df <- data.frame(Date = seq(as.Date("2000/1/1"), by = "month", length.out = 12), x = rnorm(12))

df$month <- month(df$Date, abbr = TRUE, label = TRUE)

df$moving_x <- as.numeric(stats::filter(df$x,rep(1/3,3), sides=2))

现在对于df[2,],我得到以下信息:

> df[2,]
        Date          x month     moving_x
2 2000-02-01 0.07902587   Feb -0.008438176 

我想得到的是

> df[2,]
        Date          x month     moving_x month_window
2 2000-02-01 0.07902587   Feb -0.008438176 Jan-Feb-Mar

所以我的问题是,谁能推荐一种创建month_window 的好方法,即计算移动平均线的范围?我更喜欢只使用基础 R 的解决方案。

【问题讨论】:

    标签: r


    【解决方案1】:

    这里有一些解决方案:

    1) rollapply 像这样在xmonth 上使用rollapply 和相关例程:

    library(zoo)
    
    transform(df, moving_x = rollmean(x, 3, fill = NA), 
       month_window = rollapply(month, 3, paste, collapse = "-", fill = NA))
    

    给予:

             Date           x month   moving_x month_window
    1  2000-01-01  0.37963948   Jan         NA         <NA>
    2  2000-02-01 -0.50232345   Feb -0.1519638  Jan-Feb-Mar
    3  2000-03-01 -0.33320738   Mar -0.6180354  Feb-Mar-Apr
    4  2000-04-01 -1.01857538   Apr -0.8078580  Mar-Apr-May
    5  2000-05-01 -1.07179123   May -0.5956127  Apr-May-Jun
    6  2000-06-01  0.30352864   Jun -0.1066843  May-Jun-Jul
    7  2000-07-01  0.44820978   Jul  0.2682475  Jun-Jul-Aug
    8  2000-08-01  0.05300423   Aug  0.4744938  Jul-Aug-Sep
    9  2000-09-01  0.92226747   Sep  1.0084521  Aug-Sep-Oct
    10 2000-10-01  2.05008469   Oct  0.8271070  Sep-Oct-Nov
    11 2000-11-01 -0.49103117   Nov -0.2500385  Oct-Nov-Dec
    12 2000-12-01 -2.30916888   Dec         NA         <NA>
    

    2) base 如果没有包,它会更复杂,但您可以将增加的复杂性隐藏在一个函数中,roll3,如图所示:

    roll3 <- function(x, FUN, ...) {
       if (length(x) < 3) {
           rep(NA, length(x)) 
       } else c(NA, apply(embed(x, 3)[, 3:1], 1, FUN, ...), NA)
    }
    
    transform(df, moving_x = roll3(x, mean),
                  month_window = roll3(as.character(month), paste, collapse = "-"))
    

    给予:

             Date           x month   moving_x month_window
    1  2000-01-01  0.37963948   Jan         NA         <NA>
    2  2000-02-01 -0.50232345   Feb -0.1519638  Jan-Feb-Mar
    3  2000-03-01 -0.33320738   Mar -0.6180354  Feb-Mar-Apr
    4  2000-04-01 -1.01857538   Apr -0.8078580  Mar-Apr-May
    5  2000-05-01 -1.07179123   May -0.5956127  Apr-May-Jun
    6  2000-06-01  0.30352864   Jun -0.1066843  May-Jun-Jul
    7  2000-07-01  0.44820978   Jul  0.2682475  Jun-Jul-Aug
    8  2000-08-01  0.05300423   Aug  0.4744938  Jul-Aug-Sep
    9  2000-09-01  0.92226747   Sep  1.0084521  Aug-Sep-Oct
    10 2000-10-01  2.05008469   Oct  0.8271070  Sep-Oct-Nov
    11 2000-11-01 -0.49103117   Nov -0.2500385  Oct-Nov-Dec
    12 2000-12-01 -2.30916888   Dec         NA         <NA>
    

    另外,请注意问题本身使用了一个包。月份可以这样获得:

    df$month <- format(df$Date, "%b")
    

    【讨论】:

    • 这是一个了不起的解决方案,我将把它归档以备将来应用。但是,如果可能的话,我没有提到(现在更正)我需要一个基本的 R 解决方案。
    • 已添加基础溶液。
    【解决方案2】:

    如果你想要一个唯一的基础 R 解决方案,你可以使用 sapply:

    df$window <- sapply(1:nrow(df),function(x) paste(df$month[x-1],
                                                df$month[x],
                                                df$month[x+1],sep="-"))
    

    如果您不喜欢开头和结尾的行为,您可以ifelse 无效位置的功能

    【讨论】:

      猜你喜欢
      • 2016-05-26
      • 1970-01-01
      • 2018-02-03
      • 2020-07-12
      • 1970-01-01
      • 2022-09-24
      • 2019-03-22
      • 2020-08-29
      • 2020-12-28
      相关资源
      最近更新 更多