Answers:
或者您可以使用过滤器简单地计算它,这是我使用的功能:
ma <- function(x, n = 5){filter(x, rep(1 / n, n), sides = 2)}
如果使用dplyr
,请小心stats::filter
在以上功能中指定。
stats::filter
sides = 2
相当于zoo :: rollmean或RcppRoll :: roll_mean的align =“ center”。sides = 1
等同于“正确”对齐。我没有办法进行“左”对齐或使用“部分”数据(2个或更多值)进行计算?
使用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,则将存在除以零的错误。
cumsum(c(1:3,NA,1:3))
cx <- c(0, cumsum(ifelse(is.na(x), 0, x)))
。
在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
该caTools
包装具有非常快的滚动平均值/最小值/最大值/标准偏差和其他一些功能。我只使用过,runmean
并且runsd
它们是迄今为止提到的其他所有软件包中最快的。
您可以使用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
}
res = arr
。然后有一个循环,从n
第15个元素开始迭代,直到数组的结尾。这意味着他取平均值的第一个子集arr[1:15]
填补了位置res[15]
。现在,我更喜欢设置res = rep(NA, length(arr))
而不是res = arr
让每个res[1:14]
等于NA的元素而不是等于一个数字的数字,在这里我们不能取15个元素的全部平均值。
其实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,...)]
}
}
为了补充cantdutchthis和Rodrigo Remedio的回答 ;
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)
这是示例代码,显示了如何使用zoo软件包中的函数来计算居中移动平均值和尾随移动平均值。rollmean
library(tidyverse)
library(zoo)
some_data = tibble(day = 1:10)
# cma = centered moving average
# tma = trailing moving average
some_data = some_data %>%
mutate(cma = rollmean(day, k = 3, fill = NA)) %>%
mutate(tma = rollmean(day, k = 3, fill = NA, align = "right"))
some_data
#> # A tibble: 10 x 3
#> day cma tma
#> <int> <dbl> <dbl>
#> 1 1 NA NA
#> 2 2 2 NA
#> 3 3 3 2
#> 4 4 4 3
#> 5 5 5 4
#> 6 6 6 5
#> 7 7 7 6
#> 8 8 8 7
#> 9 9 9 8
#> 10 10 NA 9
一个人可以使用runner
包装来移动功能。在这种情况下mean_run
功能。问题cummean
在于它不处理NA
值,但是mean_run
可以处理。runner
程序包还支持不规则的时间序列,并且窗口可以取决于日期:
library(runner)
set.seed(11)
x1 <- rnorm(15)
x2 <- sample(c(rep(NA,5), rnorm(15)), 15, replace = TRUE)
date <- Sys.Date() + cumsum(sample(1:3, 15, replace = TRUE))
mean_run(x1)
#> [1] -0.5910311 -0.2822184 -0.6936633 -0.8609108 -0.4530308 -0.5332176
#> [7] -0.2679571 -0.1563477 -0.1440561 -0.2300625 -0.2844599 -0.2897842
#> [13] -0.3858234 -0.3765192 -0.4280809
mean_run(x2, na_rm = TRUE)
#> [1] -0.18760011 -0.09022066 -0.06543317 0.03906450 -0.12188853 -0.13873536
#> [7] -0.13873536 -0.14571604 -0.12596067 -0.11116961 -0.09881996 -0.08871569
#> [13] -0.05194292 -0.04699909 -0.05704202
mean_run(x2, na_rm = FALSE )
#> [1] -0.18760011 -0.09022066 -0.06543317 0.03906450 -0.12188853 -0.13873536
#> [7] NA NA NA NA NA NA
#> [13] NA NA NA
mean_run(x2, na_rm = TRUE, k = 4)
#> [1] -0.18760011 -0.09022066 -0.06543317 0.03906450 -0.10546063 -0.16299272
#> [7] -0.21203756 -0.39209010 -0.13274756 -0.05603811 -0.03894684 0.01103493
#> [13] 0.09609256 0.09738460 0.04740283
mean_run(x2, na_rm = TRUE, k = 4, idx = date)
#> [1] -0.187600111 -0.090220655 -0.004349696 0.168349653 -0.206571573 -0.494335093
#> [7] -0.222969541 -0.187600111 -0.087636571 0.009742884 0.009742884 0.012326968
#> [13] 0.182442234 0.125737145 0.059094786
虽然有点慢,但是您也可以使用zoo :: rollapply对矩阵执行计算。
reqd_ma <- rollapply(x, FUN = mean, width = n)
其中x是数据集,FUN =平均值是函数;您还可以将其更改为最小值,最大值,标准差等,并且宽度是滚动窗口。
set.seed(123); x <- rnorm(1000); system.time(apply(embed(x, 5), 1, mean)); library(zoo); system.time(rollapply(x, 5, mean))
在我的机器上,它是如此之快,以至于返回了0秒的时间。
滑块包可用于此目的。它具有专门设计的感觉类似于purrr的界面。它接受任何任意函数,并且可以返回任何类型的输出。数据帧甚至逐行迭代。pkgdown站点在这里。
library(slider)
x <- 1:3
# Mean of the current value + 1 value before it
# returned as a double vector
slide_dbl(x, ~mean(.x, na.rm = TRUE), .before = 1)
#> [1] 1.0 1.5 2.5
df <- data.frame(x = x, y = x)
# Slide row wise over data frames
slide(df, ~.x, .before = 1)
#> [[1]]
#> x y
#> 1 1 1
#>
#> [[2]]
#> x y
#> 1 1 1
#> 2 2 2
#>
#> [[3]]
#> x y
#> 1 2 2
#> 2 3 3
滑块和data.table的开销都frollapply()
应该很低(比Zoo快得多)。frollapply()
对于此处的这个简单示例,它看起来要快一些,但是请注意,它仅接受数字输入,并且输出必须是标量数字值。滑块功能是完全通用的,您可以返回任何数据类型。
library(slider)
library(zoo)
library(data.table)
x <- 1:50000 + 0L
bench::mark(
slider = slide_int(x, function(x) 1L, .before = 5, .complete = TRUE),
zoo = rollapplyr(x, FUN = function(x) 1L, width = 6, fill = NA),
datatable = frollapply(x, n = 6, FUN = function(x) 1L),
iterations = 200
)
#> # A tibble: 3 x 6
#> expression min median `itr/sec` mem_alloc `gc/sec`
#> <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl>
#> 1 slider 19.82ms 26.4ms 38.4 829.8KB 19.0
#> 2 zoo 177.92ms 211.1ms 4.71 17.9MB 24.8
#> 3 datatable 7.78ms 10.9ms 87.9 807.1KB 38.7
forecast::ma
,它包含了所有街区,不对。