Statistics 朱莉娅的移动平均线
我想计算Julia中数组的简单移动平均数。我有一个简单的数组,但是我找到的所有包都需要一个TimeArray来计算移动平均值。是否有一个包不需要我人工创建一个TimeArray 那么:Statistics 朱莉娅的移动平均线,statistics,julia,moving-average,Statistics,Julia,Moving Average,我想计算Julia中数组的简单移动平均数。我有一个简单的数组,但是我找到的所有包都需要一个TimeArray来计算移动平均值。是否有一个包不需要我人工创建一个TimeArray 那么: moving_average(vs,n) = [sum(@view vs[i:(i+n-1)])/n for i in 1:(length(vs)-(n-1))] 这可以通过为循环建立一个标准,预先分配结果数组,并在每次迭代中只减去和添加输入数组的一个元素来进一步优化。但是,对于大多数应用程序,上面的简单代码就
moving_average(vs,n) = [sum(@view vs[i:(i+n-1)])/n for i in 1:(length(vs)-(n-1))]
这可以通过为循环建立一个标准,预先分配结果数组,并在每次迭代中只减去和添加输入数组的一个元素来进一步优化。但是,对于大多数应用程序,上面的简单代码就足够了 你可以像我一样写你自己的移动平均线
function movingaverage(X::Vector,numofele::Int)
BackDelta = div(numofele,2)
ForwardDelta = isodd(numofele) ? div(numofele,2) : div(numofele,2) - 1
len = length(X)
Y = similar(X)
for n = 1:len
lo = max(1,n - BackDelta)
hi = min(len,n + ForwardDelta)
Y[n] = mean(X[lo:hi])
end
return Y
end
我尝试实现了几个版本:
function rolling_sum(arr, n)
so_far = sum(arr[1:n])
out = zero(arr[n:end])
out[1] = so_far
for (i, (start, stop)) in enumerate(zip(arr, arr[n+1:end]))
so_far += stop - start
out[i+1] = so_far
end
return out
end
rolling_mean(arr, n) = rolling_sum(arr, n) ./ n
function rolling_mean2(arr, n)
return imfilter(arr, OffsetArray(fill(1/n, n), -n), Inner())
end
function rolling_mean3(arr, n)
so_far = sum(arr[1:n])
out = zero(arr[n:end])
out[1] = so_far
for (i, (start, stop)) in enumerate(zip(arr, arr[n+1:end]))
so_far += stop - start
out[i+1] = so_far / n
end
return out
end
function rolling_mean4(arr, n)
rs = cumsum(arr)[n:end] .- cumsum([0.0; arr])[1:end-n]
return rs ./ n
end
julia> v = rand(50_000);
julia> @btime(rolling_mean($v, 200));
125.362 μs (9 allocations: 1.52 MiB)
julia> @btime(rolling_mean2($v, 200));
1.089 ms (127 allocations: 3.06 MiB)
julia> @btime(rolling_mean3($v, 200));
93.137 μs (7 allocations: 1.14 MiB)
julia> @btime(rolling_mean4($v, 200));
161.613 μs (12 allocations: 2.28 MiB)
在这种情况下,似乎在每个步骤添加和删除元素的专用版本可以显著加快速度。请参阅OnlineStats.jl或RollingFunctions.jl。从技术上讲,您也可以通过DSP的卷积来实现这一点。jl@FredrikBagge我认为这是一个足够好的答案,如果你添加相应的链接!另请注意:可以使用
统计
模块中的平均值
,而不是总和
。然后,您可以通过使用技巧
(如果需要的话)扩展此代码,以更轻松地处理缺失的
。
function rolling_sum(arr, n)
so_far = sum(arr[1:n])
out = zero(arr[n:end])
out[1] = so_far
for (i, (start, stop)) in enumerate(zip(arr, arr[n+1:end]))
so_far += stop - start
out[i+1] = so_far
end
return out
end
rolling_mean(arr, n) = rolling_sum(arr, n) ./ n
function rolling_mean2(arr, n)
return imfilter(arr, OffsetArray(fill(1/n, n), -n), Inner())
end
function rolling_mean3(arr, n)
so_far = sum(arr[1:n])
out = zero(arr[n:end])
out[1] = so_far
for (i, (start, stop)) in enumerate(zip(arr, arr[n+1:end]))
so_far += stop - start
out[i+1] = so_far / n
end
return out
end
function rolling_mean4(arr, n)
rs = cumsum(arr)[n:end] .- cumsum([0.0; arr])[1:end-n]
return rs ./ n
end
julia> v = rand(50_000);
julia> @btime(rolling_mean($v, 200));
125.362 μs (9 allocations: 1.52 MiB)
julia> @btime(rolling_mean2($v, 200));
1.089 ms (127 allocations: 3.06 MiB)
julia> @btime(rolling_mean3($v, 200));
93.137 μs (7 allocations: 1.14 MiB)
julia> @btime(rolling_mean4($v, 200));
161.613 μs (12 allocations: 2.28 MiB)