计算 R 中各列的移动平均值

calculate moving average across columns in R

我有一个时间序列数据,每 3 年我想要一个移动平均值。我已经看到 TTRSMA 查询,但它们都表明滚动平均值或移动平均值操作是在单个列行上执行的,并且基于该行意味着用数字创建了一个新列NA 取决于 k 值。

我希望生成的数据帧与具有移动平均值的原始数据一样。由于我的 window 将为 3,这意味着将使用中心列和 2 个相邻列。我们可以转储第一列和最后一列以防万一,因为它们没有相邻的列。

假设数据如下:

   1961 1962 1963 1964 1965 1966 1967
1    9   13    8    4   15    1   19
2   14    2   10    6   15    7   17
3   16    7    1   18    3    9    6

我的想法是在这里寻求一些详细说明。

对于1962 <- c(9+13+8/3, 14+2+10/3, 16+7+1/3) 依此类推连续的列。第一列和最后一列可以有 NAs.

这类问题通常与重塑数据有关。为了计算滚动均值,格式应该是长格式,数据是宽格式。请参阅 this post 了解如何将数据从宽格式重塑为长格式。
然后使用函数 rollmean、包 zoo.
计算均值 最后重塑回宽幅面。

library(dplyr)
library(tidyr)

jj1 %>%
  mutate(id = row_number()) %>%
  pivot_longer(
    cols = -id,
    names_to = 'year',
    values_to = 'value'
  ) %>%
  arrange(id, year) %>%
  group_by(id) %>%
  mutate(value = zoo::rollmean(value, k = 3, fill = NA)) %>%
  pivot_wider(
    id_cols = id,
    names_from = year,
    values_from = value
  ) %>%
  ungroup() %>%
  select(-id)

您可以通过简单地在 R 中使用循环来做到这一点:

#generating some dummy data
datad <- matrix(rnorm(100), ncol = 10)
colnames(datad) <- 2001:2010

ma <- list() #moving average
for(i in 2:(ncol(datad)-1)) {
  ma[[i-1]] <- apply(datad[, (i-1):(i+1)], 1, mean)
}

#convert back to matrix
ma <- Reduce(cbind, ma)
#getting original column name
colnames(ma) <- colnames(datad)[2:(ncol(datad)-1)]

假设问题的目的是c((9+13+8)/3, (14+2+10)/3, (16+7+1)/3) 作为 1962 年的值而不是此处显示的值,rollmean 可以按以下任一方式使用。这些 one-liners 给出矩阵作为结果,但如果它是一个数据框很重要,则 as.data.frame 可以用于结果。

library(zoo)

t(apply(DF, 1, rollmean, 3))
##      1962   1963    1964    1965   1966
## 1 10.0000 8.3333  9.0000  6.6667 11.667
## 2  8.6667 6.0000 10.3333  9.3333 13.000
## 3  8.0000 8.6667  7.3333 10.0000  6.000

t(rollmean(t(DF), 3))
##      [,1]   [,2]    [,3]    [,4]   [,5]
## 1 10.0000 8.3333  9.0000  6.6667 11.667
## 2  8.6667 6.0000 10.3333  9.3333 13.000
## 3  8.0000 8.6667  7.3333 10.0000  6.000

备注

可重现形式的输入:

Lines <- "
   1961 1962 1963 1964 1965 1966 1967
1    9   13    8    4   15    1   19
2   14    2   10    6   15    7   17
3   16    7    1   18    3    9    6"
DF <- read.table(text = Lines, check.names = FALSE)