【问题标题】:Using rollmean to calculate a moving average excluding the first observation in R使用 rollmean 计算移动平均值,不包括 R 中的第一个观察值
【发布时间】:2018-10-04 23:11:14
【问题描述】:

我目前正在将 Stata 中时间序列数据的一些命令转换为 R。我正在使用 zoo 包来计算 R 中的移动平均值。这是我的数据的样子:

data <- cbind(c(1960:1970), c(95.5, 95.3, 95.3, 95.7, 95.7, 95.7, 
95.1, 95.1, 95.1, 95, 95))

      [,1] [,2]
 [1,] 1960 95.5
 [2,] 1961 95.3
 [3,] 1962 95.3
 [4,] 1963 95.7
 [5,] 1964 95.7
 [6,] 1965 95.7
 [7,] 1966 95.1
 [8,] 1967 95.1
 [9,] 1968 95.1
[10,] 1969 95.0
[11,] 1970 95.0

我会把它变成data.frame:

data <- as.data.frame(data)

现在,我可以使用rollmean 函数用我的数据计算turnout 的移动平均值:

data$turnout <- rollmean(data[,2], 1, fill = NA)

这就是我得到的:

     V1   V2 turnout
1  1960 95.5 95.5
2  1961 95.3 95.3
3  1962 95.3 95.3
4  1963 95.7 95.7
5  1964 95.7 95.7
6  1965 95.7 95.7
7  1966 95.1 95.1
8  1967 95.1 95.1
9  1968 95.1 95.1
10 1969 95.0 95.0
11 1970 95.0 95.0

这一切都很好,但我的问题是我希望我的专栏 turnout(移动平均线)从 1961 年而不是 1960 年开始。这段代码不排除第一个观察结果,这就是我想要做的做。

作为参考,等效的 Stata 命令为:

tssmooth ma m1turnout = turnout, window (1 0)

我已经尝试过使用align = "right" 函数,但这似乎不起作用。有什么想法吗?

提前致谢!

编辑——澄清一下,我这样做的长度不同。在 Stata 中,完整的代码就是这样,其中since 是一个变量,用于描述干预后的年数。

foreach y of numlist 1(1)10{
        tssmooth ma m`y'turnout = turnout, window (`y' 0)
    }
    gen dvturnout=.
    foreach y of numlist 2(1)9{
        replace dvturnout = l1.turnout if since==1
        replace dvturnout = m`y'turnout if since==`y' & m`y'turnout!=.
        replace dvturnout = m10turnout if (since==10 & m10turnout!=.) | (since==. & redist!=. & m10turnout!=.)
    }
foreach y of numlist 1(1)10{
        drop m`y'turnout
    }

我的最终目标是这个dvturnout 变量。

当我尝试我认为对应于 Stata 中第一部分代码的内容时,即:

 foreach y of numlist 1(1)10{
        tssmooth ma m`y'turnout = turnout, window (`y' 0)
    }

在 R 中,我这样做([,35] 是我开始添加变量的列):

for (j in 1:10) {
  data_countries[[i]][,35+j] <- rollmean(data_countries[[i]][,13], j, fill = NA, align = "right")
}
}

它为我吐出了这个:

year since  V36   V37      V38    V39   V40      V41      V42     V43      V44   V45
1  1960    NA 95.5    NA       NA     NA    NA       NA       NA      NA       NA    NA
2  1961    NA 95.3 95.40       NA     NA    NA       NA       NA      NA       NA    NA
3  1962    NA 95.3 95.30 95.36667     NA    NA       NA       NA      NA       NA    NA
4  1963    NA 95.7 95.50 95.43333 95.450    NA       NA       NA      NA       NA    NA
5  1964    NA 95.7 95.70 95.56667 95.500 95.50       NA       NA      NA       NA    NA
6  1965    NA 95.7 95.70 95.70000 95.600 95.54 95.53333       NA      NA       NA    NA
7  1966    NA 95.1 95.40 95.50000 95.550 95.50 95.46667 95.47143      NA       NA    NA
8  1967    NA 95.1 95.10 95.30000 95.400 95.46 95.43333 95.41428 95.4250       NA    NA
9  1968    NA 95.1 95.10 95.10000 95.250 95.34 95.40000 95.38571 95.3750 95.38889    NA
10 1969    NA 95.0 95.05 95.06667 95.075 95.20 95.28333 95.34286 95.3375 95.33333 95.35
11 1970    NA 95.0 95.00 95.03333 95.050 95.06 95.16667 95.24286 95.3000 95.30000 95.30

这些数字都很好,但是它们从我想要的位置“移动”了下来。这是Stata中相同的操作给我的:

year    dvturnout   m1turnout   m2turnout   m3turnout   m4turnout   m5turnout   m6turnout   m7turnout   m8turnout   m9turnout   m10turnout
1960                                            
1961        95.5    95.5    95.5    95.5    95.5    95.5    95.5    95.5    95.5    95.5
1962        95.3    95.4    95.4    95.4    95.4    95.4    95.4    95.4    95.4    95.4
1963        95.3    95.3    95.36667    95.36667    95.36667    95.36667    95.36667    95.36667    95.36667    95.36667
1964        95.7    95.5    95.43333    95.45   95.45   95.45   95.45   95.45   95.45   95.45
1965        95.7    95.7    95.56667    95.5    95.5    95.5    95.5    95.5    95.5    95.5
1966        95.7    95.7    95.7    95.6    95.54   95.53333    95.53333    95.53333    95.53333    95.53333
1967        95.1    95.39999    95.5    95.55   95.5    95.46667    95.47143    95.47143    95.47143    95.47143
1968        95.1    95.1    95.3    95.39999    95.46   95.43333    95.41428    95.425  95.425  95.425
1969        95.1    95.1    95.1    95.25   95.34   95.39999    95.38571    95.375  95.38889    95.38889
1970        95  95.05   95.06667    95.075  95.2    95.28333    95.34286    95.3375 95.33334    95.35

【问题讨论】:

  • 期望的输出是什么?考虑到标量的平均值是它本身,使用长度为 1 的滚动平均值有什么意义?
  • 非常感谢您的回复。我已经在原始帖子中添加了说明。我正在将 Stata 中的代码复制到 R 中。
  • 感谢您的澄清。我想我现在明白你在追求什么了。更新答案。

标签: r time-series zoo moving-average


【解决方案1】:

您需要的是一个不包括当前观察值的移动平均函数。谢天谢地,w_i_l_l wrote a function exactly like that。是什么让事情变得复杂:你论文的作者用上一列的结果填充了没有足够数据(例如,k = 4,但只有 3 个数据点)的移动平均线。我真的不建议这样做,因为如果没有非常明确地指出,这可能(并且通常会)导致严重的混乱。

代码

# w_i_l_l's moving average function
mav <- function(x,n){filter(x,rep(1/n,n), sides=1)} 
mavback <- function(x,n){
               a<-mav(x,1)
               b<-mav(x,(n+1))
               c<-(1/n)*((n+1)*b - a)
               return(c)
           }

# Create 10 columns with moving averages of k = 1:10
result <- NULL
for(i in 1:10){
    result <- cbind(result,mavback(test[,2], i))
}

# Give propers names to columns
colnames(result) <- paste0("m", 1:ncol(result)-1,"turnout")

# Combine result with base data
result <- cbind(test,data.frame(result))

# WONKY STATISTICS: If there is a NA (= not enough data for a
# moving average) fill it up with previous column's result
for(i in 4:ncol(result)){
    # Nested loop starts from first row
    for(j in 2:nrow(result)){
        # Check for NA
        if(is.na(result[j,i])){
            result[j,i] <- result[j,i-1]
        }
    }
}

结果

> result
   year turnout m0turnout m1turnout m2turnout m3turnout m4turnout m5turnout m6turnout m7turnout m8turnout m9turnout
1  1960    95.5        NA        NA        NA        NA        NA        NA        NA        NA        NA        NA
2  1961    95.3      95.5     95.50  95.50000  95.50000  95.50000  95.50000  95.50000  95.50000  95.50000  95.50000
3  1962    95.3      95.3     95.40  95.40000  95.40000  95.40000  95.40000  95.40000  95.40000  95.40000  95.40000
4  1963    95.7      95.3     95.30  95.36667  95.36667  95.36667  95.36667  95.36667  95.36667  95.36667  95.36667
5  1964    95.7      95.7     95.50  95.43333  95.45000  95.45000  95.45000  95.45000  95.45000  95.45000  95.45000
6  1965    95.7      95.7     95.70  95.56667  95.50000  95.50000  95.50000  95.50000  95.50000  95.50000  95.50000
7  1966    95.1      95.7     95.70  95.70000  95.60000  95.54000  95.53333  95.53333  95.53333  95.53333  95.53333
8  1967    95.1      95.1     95.40  95.50000  95.55000  95.50000  95.46667  95.47143  95.47143  95.47143  95.47143
9  1968    95.1      95.1     95.10  95.30000  95.40000  95.46000  95.43333  95.41429  95.42500  95.42500  95.42500
10 1969    95.0      95.1     95.10  95.10000  95.25000  95.34000  95.40000  95.38571  95.37500  95.38889  95.38889
11 1970    95.0      95.0     95.05  95.06667  95.07500  95.20000  95.28333  95.34286  95.33750  95.33333  95.35000

没有“填满”的结果

> result
   year turnout m0turnout m1turnout m2turnout m3turnout m4turnout m5turnout m6turnout m7turnout m8turnout m9turnout
1  1960    95.5        NA        NA        NA        NA        NA        NA        NA        NA        NA        NA
2  1961    95.3      95.5        NA        NA        NA        NA        NA        NA        NA        NA        NA
3  1962    95.3      95.3     95.40        NA        NA        NA        NA        NA        NA        NA        NA
4  1963    95.7      95.3     95.30  95.36667        NA        NA        NA        NA        NA        NA        NA
5  1964    95.7      95.7     95.50  95.43333    95.450        NA        NA        NA        NA        NA        NA
6  1965    95.7      95.7     95.70  95.56667    95.500     95.50        NA        NA        NA        NA        NA
7  1966    95.1      95.7     95.70  95.70000    95.600     95.54  95.53333        NA        NA        NA        NA
8  1967    95.1      95.1     95.40  95.50000    95.550     95.50  95.46667  95.47143        NA        NA        NA
9  1968    95.1      95.1     95.10  95.30000    95.400     95.46  95.43333  95.41429   95.4250        NA        NA
10 1969    95.0      95.1     95.10  95.10000    95.250     95.34  95.40000  95.38571   95.3750  95.38889        NA
11 1970    95.0      95.0     95.05  95.06667    95.075     95.20  95.28333  95.34286   95.3375  95.33333     95.35

数据

test <- data.frame(cbind(year = c(1960:1970), 
                         turnout = c(95.5, 95.3, 95.3, 95.7, 95.7,
                                     95.7, 95.1, 95.1, 95.1, 95, 95)))

【讨论】:

  • 谢谢,这真的很有帮助。你是对的。老实说,我对我对移动平均线的理解并不是 100% 满意(以防你无法分辨)。我正在尝试为一门课程复制一篇论文,它必须在 R 中完成,但作者提供的数据/命令在 Stata 中。我在原始帖子中添加了对我最终目标的说明,包括相应的 Stata 命令。也许在 R 中有更简单的方法?
  • @Zereg,非常感谢您的澄清。我想我终于明白你在追求什么了。作者确实使用了滚动平均值,但有两个警告:1)它不使用当前观察值(这很容易解决)和 2)在计算后他们用之前的值填充了他们的 NA列的数据(/ 只使用了可用的数据)。我不想听起来居高临下,但后者似乎……至少是靠不住的?特别是,因为它似乎没有被明确指出。无论如何,代码现在给出了预期的输出。
  • 这绝对是一件非常令人困惑的事情!你确实捕捉到了他们所做的一切。我更仔细地翻阅了技术文档,结果发现这组 10 个新生成的变量仅用作中间计算步骤。最终,作者有选择地使用基于另一个变量since(干预后的年数)的移动平均线的结果。原来其余的代码(我在询问时没有写)甚至根本不需要“填充”值。只需使用 NA 就可以了。非常感谢!
  • 另外注意,我发现你可以通过使用 R 中的lag 命令复制 w_i_l_l 的移动平均函数(即不包括当前观察的移动平均函数):data$turnout &lt;- lag(rollmean(data[,2], 1, fill = NA),1) Much更简单的方法:)
【解决方案2】:

也许你正在寻找这样的东西:

library(zoo)
library(forecast)
data <- cbind(c(1960:1970), c(95.5, 95.3, 95.3, 95.7, 95.7, 95.7, 95.1, 95.1, 95.1, 95, 95)) 
x1 <- ts(data = data[, 2], start = 1960, end = 1970, frequency = 1)
x2 <- cbind(x1, turnout = zoo::rollmeanr(x1, k = 2))

打印时间序列对象:

x2
Time Series:
Start = 1960 
End = 1970 
Frequency = 1 
       x1 turnout
1960 95.5      NA
1961 95.3   95.40
1962 95.3   95.30
1963 95.7   95.50
1964 95.7   95.70
1965 95.7   95.70
1966 95.1   95.40
1967 95.1   95.10
1968 95.1   95.10
1969 95.0   95.05
1970 95.0   95.00

剧情:

forecast::autoplot(x2)

【讨论】:

    【解决方案3】:

    我发现最简单的方法是使用 lag 函数。

    data$turnout <- lag(rollmean(data[,2], 1, fill = NA),1)
    

    【讨论】:

      猜你喜欢
      • 2017-01-02
      • 1970-01-01
      • 1970-01-01
      • 2021-02-08
      • 1970-01-01
      • 1970-01-01
      • 2021-11-22
      • 2019-04-03
      • 2016-10-02
      相关资源
      最近更新 更多