Statistics 朱莉娅的移动平均线

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))] 这可以通过为循环建立一个标准,预先分配结果数组,并在每次迭代中只减去和添加输入数组的一个元素来进一步优化。但是,对于大多数应用程序,上面的简单代码就

我想计算Julia中数组的简单移动平均数。我有一个简单的数组,但是我找到的所有包都需要一个TimeArray来计算移动平均值。是否有一个包不需要我人工创建一个TimeArray

那么:

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)