Я пытаюсь использовать R для вычисления скользящей средней по ряду значений в матрице. Обычный поиск в списке рассылки R не очень помог. Кажется, что встроенная функция в R позволит мне рассчитать скользящие средние. Предоставляются ли какие-либо пакеты? Или мне нужно написать свой собственный?
Расчет скользящей средней
Ответ 1
Ответ 2
Или вы можете просто рассчитать его с помощью фильтра, здесь функция, которую я использую:
ma <- function(x, n = 5){filter(x, rep(1 / n, n), sides = 2)}
Если вы используете dplyr
, будьте осторожны, dplyr
stats::filter
в функции выше.
Ответ 3
Использование cumsum
должно быть достаточным и эффективным. Предполагая, что у вас есть вектор x, и вы хотите получить текущую сумму из n чисел
cx <- c(0,cumsum(x))
rsum <- (cx[(n+1):length(cx)] - cx[1:(length(cx) - n)]) / n
Как указано в комментариях @mzuther, это предполагает, что в данных нет NA. чтобы справиться с этим, потребуется разделить каждое окно на количество значений, отличных от NA. Вот один из способов сделать это, включив комментарий @Ricardo Cruz:
cx <- c(0, cumsum(ifelse(is.na(x), 0, x)))
cn <- c(0, cumsum(ifelse(is.na(x), 0, 1)))
rx <- cx[(n+1):length(cx)] - cx[1:(length(cx) - n)]
rn <- cn[(n+1):length(cx)] - cn[1:(length(cx) - n)]
rsum <- rx / rn
Это все еще имеет проблему, что, если все значения в окне являются NA, тогда будет ошибка деления на ноль.
Ответ 4
Пакет caTools
имеет очень быстрое скользящее среднее/мин/макс/сд и несколько других функций. Я работал только с runmean
и runsd
, и они являются самыми быстрыми из любых других пакетов, упомянутых на сегодняшний день.
Ответ 5
Вы можете использовать RcppRoll
для очень быстрых скользящих средних, написанных в C++. Просто вызовите функцию roll_mean
. Документы можно найти здесь.
В противном случае этот (более медленный) цикл for должен сработать:
ma <- function(arr, n=15){
res = arr
for(i in n:length(arr)){
res[i] = mean(arr[(i-n):i])
}
res
}
Ответ 6
В data.table 1.12.0 была добавлена новая функция frollmean
для вычисления быстрого и точного скользящего среднего, тщательно обрабатывая значения NA
, NaN
и +Inf
, -Inf
.
Так как в этом вопросе нет воспроизводимого примера, здесь не так много вопросов.
Вы можете найти более подробную информацию о ?frollmean
в руководстве, также доступном онлайн по адресу ?frollmean
.
Примеры из руководства ниже:
library(data.table)
d = as.data.table(list(1:6/2, 3:8/4))
# rollmean of single vector and single window
frollmean(d[, V1], 3)
# multiple columns at once
frollmean(d, 3)
# multiple windows at once
frollmean(d[, .(V1)], c(3, 4))
# multiple columns and multiple windows at once
frollmean(d, c(3, 4))
## three above are embarrassingly parallel using openmp
Ответ 7
На самом деле RcppRoll
очень хорошо.
Код, отправленный cantdutchthis, должен быть исправлен в четвертой строке, чтобы окно было исправлено:
ma <- function(arr, n=15){
res = arr
for(i in n:length(arr)){
res[i] = mean(arr[(i-n+1):i])
}
res
}
Другой способ, который обрабатывает пропуски, дается здесь.
Третий способ, улучшающий cantdutchthis код для вычисления частичных средних или нет, следует:
ma <- function(x, n=2,parcial=TRUE){
res = x #set the first values
if (parcial==TRUE){
for(i in 1:length(x)){
t<-max(i-n+1,1)
res[i] = mean(x[t:i])
}
res
}else{
for(i in 1:length(x)){
t<-max(i-n+1,1)
res[i] = mean(x[t:i])
}
res[-c(seq(1,n-1,1))] #remove the n-1 first,i.e., res[c(-3,-4,...)]
}
}
Ответ 8
Чтобы дополнить ответ cantdutchthis и Родриго Ремедио,
moving_fun <- function(x, w, FUN, ...) {
# x: a double vector
# w: the length of the window, i.e., the section of the vector selected to apply FUN
# FUN: a function that takes a vector and return a summarize value, e.g., mean, sum, etc.
# Given a double type vector apply a FUN over a moving window from left to the right,
# when a window boundary is not a legal section, i.e. lower_bound and i (upper bound)
# are not contained in the length of the vector, return a NA_real_
if (w < 1) {
stop("The length of the window 'w' must be greater than 0")
}
output <- x
for (i in 1:length(x)) {
# plus 1 because the index is inclusive with the upper_bound 'i'
lower_bound <- i - w + 1
if (lower_bound < 1) {
output[i] <- NA_real_
} else {
output[i] <- FUN(x[lower_bound:i, ...])
}
}
output
}
# example
v <- seq(1:10)
# compute a MA(2)
moving_fun(v, 2, mean)
# compute moving sum of two periods
moving_fun(v, 2, sum)
Ответ 9
все параметры, перечисленные здесь, являются каузальными скользящими средними. если требуется не причинная версия, тогда пакет сигнал имеет некоторые параметры.
Ответ 10
Хотя и немного медленно, но вы также можете использовать zoo :: rollapply для выполнения вычислений на матрицах.
reqd_ma <- rollapply(x, FUN = mean, width = n)
где x - набор данных, FUN = mean - функция; Вы также можете изменить его на min, max, sd и т.д., а width - это скользящее окно.