Uyuşuk / scipy'deki hareketli ortalamayı basitçe hesaplayan ve kıvrımlı çözümlere yol açan bir işlev yok gibi görünüyor .
Sorum iki yönlü:
Uyuşuk / scipy'deki hareketli ortalamayı basitçe hesaplayan ve kıvrımlı çözümlere yol açan bir işlev yok gibi görünüyor .
Sorum iki yönlü:
Yanıtlar:
Sadece basit istiyorsanız ortalama hareketli olmayan ağırlıklı, kolayca ile bunu uygulayabilirsiniz np.cumsum
hangi olabilir olan hızlı FFT daha temelli yöntemler:
DÜZENLE Bean tarafından kodda tespit edilen bir defaya mahsus yanlış indeksleme düzeltildi. DÜZENLE
def moving_average(a, n=3) :
ret = np.cumsum(a, dtype=float)
ret[n:] = ret[n:] - ret[:-n]
return ret[n - 1:] / n
>>> a = np.arange(20)
>>> moving_average(a)
array([ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11.,
12., 13., 14., 15., 16., 17., 18.])
>>> moving_average(a, n=4)
array([ 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5,
10.5, 11.5, 12.5, 13.5, 14.5, 15.5, 16.5, 17.5])
Bu yüzden sanırım cevap şu: Uygulanması gerçekten çok kolay ve belki de numpy zaten özel işlevlerle biraz şişirilmiş durumda.
ret[n:] -= ret[:-n]
AYNI DEĞİLDİR ret[n:] = ret[n:] - ret[:-n]
. Bu cevaptaki kodu düzelttim. Düzenleme: Hayır, başka biri beni dövdü.
NumPy'nin belirli bir alana özgü işlev eksikliği, belki de Çekirdek Ekibin disiplini ve NumPy'nin ana direktifine olan sadakatinden kaynaklanmaktadır: N boyutlu bir dizi türü ve bu dizileri oluşturma ve indeksleme işlevleri sağlayın . Birçok temel amaç gibi, bu da küçük değildir ve NumPy bunu zekice yapar.
(Çok) daha büyük olan SciPy , çok daha geniş bir alana özgü kitaplık koleksiyonunu içerir ( SciPy geliştiricileri tarafından alt paketler olarak adlandırılır ) - örneğin, sayısal optimizasyon ( optimize ), sinyal işleme ( sinyal ) ve integral hesaplama ( integral ).
Benim tahminim, peşinde olduğunuz işlev SciPy alt paketlerinden en az birinde ( belki scipy.signal ); ancak, önce SciPy scikitlerinin koleksiyonuna bakar , ilgili scikit (ler) i tanımlar ve oradaki ilgili işlevi arardım.
Scikits bağımsız belirli bir teknik disiplin (örneğin üzere NumPy / SciPy dayalı paketleri geliştirdi ve yönlendirilir scikits-görüntü , scikits-öğrenme (özellikle müthiş Bunlardan birkaç vs.) OpenOpt , sayısal optimizasyon için) saygın edildi nispeten yeni scikits değerlendirme tablosu altında kalmayı seçmeden çok önce olgun projeler . Scikits 30 tür yaklaşık Yukarıdaki listelere sevdim Anasayfa scikits en az olanların birkaç artık aktif geliştirilme aşamasındadır olsa.
Bu tavsiyeye uymanız sizi scikits zaman serilerine götürecektir ; ancak, bu paket artık aktif geliştirme aşamasındadır; Aslında Pandalar , AFAIK, fiilen NumPy tabanlı zaman serisi kitaplığı haline geldi .
Pandaların hareketli ortalamayı hesaplamak için kullanılabilecek çeşitli işlevleri vardır ; bunların en basiti muhtemelen şu şekilde kullandığınız yuvarlanan_ortadır :
>>> # the recommended syntax to import pandas
>>> import pandas as PD
>>> import numpy as NP
>>> # prepare some fake data:
>>> # the date-time indices:
>>> t = PD.date_range('1/1/2010', '12/31/2012', freq='D')
>>> # the data:
>>> x = NP.arange(0, t.shape[0])
>>> # combine the data & index into a Pandas 'Series' object
>>> D = PD.Series(x, t)
Şimdi, sadece Series nesnesinde geçen rolling_mean işlevini ve aşağıdaki örneğimde 10 gün olan bir pencere boyutunu çağırın .
>>> d_mva = PD.rolling_mean(D, 10)
>>> # d_mva is the same size as the original Series
>>> d_mva.shape
(1096,)
>>> # though obviously the first w values are NaN where w is the window size
>>> d_mva[:3]
2010-01-01 NaN
2010-01-02 NaN
2010-01-03 NaN
çalıştığını doğrulayın - örneğin, orijinal serideki 10 - 15 arasındaki değerleri yuvarlanan ortalama ile yumuşatılmış yeni Seri ile karşılaştırdı
>>> D[10:15]
2010-01-11 2.041076
2010-01-12 2.041076
2010-01-13 2.720585
2010-01-14 2.720585
2010-01-15 3.656987
Freq: D
>>> d_mva[10:20]
2010-01-11 3.131125
2010-01-12 3.035232
2010-01-13 2.923144
2010-01-14 2.811055
2010-01-15 2.785824
Freq: D
Rolling_mean işlevi, yaklaşık bir düzine kadar başka işlevle birlikte Pandas belgelerinde, rubrik hareketli pencere işlevleri altında gayri resmi olarak gruplandırılmıştır ; Pandalar'daki ikinci, ilgili işlevler grubu üstel ağırlıklı işlevler olarak adlandırılır (örneğin, üssel olarak hareketli ağırlıklı ortalamayı hesaplayan ewma ). Bu ikinci grubun birinci gruba ( hareketli pencere fonksiyonları) dahil olmaması , belki de üstel ağırlıklı dönüşümlerin sabit uzunlukta bir pencereye dayanmamasından kaynaklanmaktadır.
Bunu başarmanın basit bir yolu kullanmaktır np.convolve
. Bunun arkasındaki fikir, ayrık evrişimin hesaplanma şeklinden yararlanmak ve onu bir yuvarlanan ortalama döndürmek için kullanmaktır . Bu, np.ones
istediğimiz sürgülü pencere uzunluğuna eşit bir uzunlukta bir dizi ile bükülerek yapılabilir .
Bunu yapmak için aşağıdaki işlevi tanımlayabiliriz:
def moving_average(x, w):
return np.convolve(x, np.ones(w), 'valid') / w
Bu fonksiyon, dizinin evrişimini x
ve uzunluktaki bir diziyi alacak w
. Seçilen Not mode
olan valid
konvolüsyon ürün sadece sekanslar tamamen üst üste puan verilir, böylece.
Bazı örnekler:
x = np.array([5,3,8,10,2,1,5,1,0,2])
Bir pencere uzunluğuna sahip hareketli bir ortalama için sahip 2
oluruz:
moving_average(x, 2)
# array([4. , 5.5, 9. , 6. , 1.5, 3. , 3. , 0.5, 1. ])
Ve uzun bir pencere için 4
:
moving_average(x, 4)
# array([6.5 , 5.75, 5.25, 4.5 , 2.25, 1.75, 2. ])
convolve
çalışır?Ayrık evrişimin hesaplanma şekline daha derinlemesine bakalım. Aşağıdaki işlev np.convolve
, çıktı değerlerini hesaplamanın yolunu kopyalamayı amaçlamaktadır :
def mov_avg(x, w):
for m in range(len(x)-(w-1)):
yield sum(np.ones(w) * x[m:m+w]) / w
Yukarıdaki aynı örnek için aynı zamanda şunu da verir:
list(mov_avg(x, 2))
# [4.0, 5.5, 9.0, 6.0, 1.5, 3.0, 3.0, 0.5, 1.0]
Yani her adımda yapılan şey, iç çarpımı birler dizisi ile mevcut pencere arasına almaktır . Bu durumda, np.ones(w)
doğrudan sum
diziyi aldığımız için çarpma işlemi gereksizdir .
Körük, biraz daha net olması için ilk çıktıların nasıl hesaplandığına bir örnektir. Bir pencere istediğimizi varsayalım w=4
:
[1,1,1,1]
[5,3,8,10,2,1,5,1,0,2]
= (1*5 + 1*3 + 1*8 + 1*10) / w = 6.5
Ve aşağıdaki çıktı şu şekilde hesaplanacaktır:
[1,1,1,1]
[5,3,8,10,2,1,5,1,0,2]
= (1*3 + 1*8 + 1*10 + 1*2) / w = 5.75
Ve böylece, tüm örtüşmeler gerçekleştirildikten sonra dizinin hareketli bir ortalamasını döndürür.
mode='valid'
değiştirilebilir 'same'
. Sadece bu durumda kenar noktaları sıfıra doğru çekilecektir.
İşte bunu yapmanın çeşitli yolları ve bazı kriterler. En iyi yöntemler, diğer kitaplıklardan optimize edilmiş kod kullanan sürümlerdir. bottleneck.move_mean
Yöntem muhtemelen en iyi her yerde. scipy.convolve
Yaklaşım aynı zamanda çok hızlı, genişletilebilir ve sözdizimsel ve kavramsal basit, ama çok büyük pencere değerleri için iyi ölçek değildir. numpy.cumsum
Saf bir gerekiyorsa yöntem iyidir numpy
yaklaşımı.
Not: Bunlardan bazıları (örneğin bottleneck.move_mean
) ortalanmamıştır ve verilerinizi değiştirecektir.
import numpy as np
import scipy as sci
import scipy.signal as sig
import pandas as pd
import bottleneck as bn
import time as time
def rollavg_direct(a,n):
'Direct "for" loop'
assert n%2==1
b = a*0.0
for i in range(len(a)) :
b[i]=a[max(i-n//2,0):min(i+n//2+1,len(a))].mean()
return b
def rollavg_comprehension(a,n):
'List comprehension'
assert n%2==1
r,N = int(n/2),len(a)
return np.array([a[max(i-r,0):min(i+r+1,N)].mean() for i in range(N)])
def rollavg_convolve(a,n):
'scipy.convolve'
assert n%2==1
return sci.convolve(a,np.ones(n,dtype='float')/n, 'same')[n//2:-n//2+1]
def rollavg_convolve_edges(a,n):
'scipy.convolve, edge handling'
assert n%2==1
return sci.convolve(a,np.ones(n,dtype='float'), 'same')/sci.convolve(np.ones(len(a)),np.ones(n), 'same')
def rollavg_cumsum(a,n):
'numpy.cumsum'
assert n%2==1
cumsum_vec = np.cumsum(np.insert(a, 0, 0))
return (cumsum_vec[n:] - cumsum_vec[:-n]) / n
def rollavg_cumsum_edges(a,n):
'numpy.cumsum, edge handling'
assert n%2==1
N = len(a)
cumsum_vec = np.cumsum(np.insert(np.pad(a,(n-1,n-1),'constant'), 0, 0))
d = np.hstack((np.arange(n//2+1,n),np.ones(N-n)*n,np.arange(n,n//2,-1)))
return (cumsum_vec[n+n//2:-n//2+1] - cumsum_vec[n//2:-n-n//2]) / d
def rollavg_roll(a,n):
'Numpy array rolling'
assert n%2==1
N = len(a)
rolling_idx = np.mod((N-1)*np.arange(n)[:,None] + np.arange(N), N)
return a[rolling_idx].mean(axis=0)[n-1:]
def rollavg_roll_edges(a,n):
# see /programming/42101082/fast-numpy-roll
'Numpy array rolling, edge handling'
assert n%2==1
a = np.pad(a,(0,n-1-n//2), 'constant')*np.ones(n)[:,None]
m = a.shape[1]
idx = np.mod((m-1)*np.arange(n)[:,None] + np.arange(m), m) # Rolling index
out = a[np.arange(-n//2,n//2)[:,None], idx]
d = np.hstack((np.arange(1,n),np.ones(m-2*n+1+n//2)*n,np.arange(n,n//2,-1)))
return (out.sum(axis=0)/d)[n//2:]
def rollavg_pandas(a,n):
'Pandas rolling average'
return pd.DataFrame(a).rolling(n, center=True, min_periods=1).mean().to_numpy()
def rollavg_bottlneck(a,n):
'bottleneck.move_mean'
return bn.move_mean(a, window=n, min_count=1)
N = 10**6
a = np.random.rand(N)
functions = [rollavg_direct, rollavg_comprehension, rollavg_convolve,
rollavg_convolve_edges, rollavg_cumsum, rollavg_cumsum_edges,
rollavg_pandas, rollavg_bottlneck, rollavg_roll, rollavg_roll_edges]
print('Small window (n=3)')
%load_ext memory_profiler
for f in functions :
print('\n'+f.__doc__+ ' : ')
%timeit b=f(a,3)
print('\nLarge window (n=1001)')
for f in functions[0:-2] :
print('\n'+f.__doc__+ ' : ')
%timeit b=f(a,1001)
print('\nMemory\n')
print('Small window (n=3)')
N = 10**7
a = np.random.rand(N)
%load_ext memory_profiler
for f in functions[2:] :
print('\n'+f.__doc__+ ' : ')
%memit b=f(a,3)
print('\nLarge window (n=1001)')
for f in functions[2:-2] :
print('\n'+f.__doc__+ ' : ')
%memit b=f(a,1001)
Zamanlama, Küçük pencere (n = 3)
Direct "for" loop :
4.14 s ± 23.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
List comprehension :
3.96 s ± 27.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
scipy.convolve :
1.07 ms ± 26.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
scipy.convolve, edge handling :
4.68 ms ± 9.69 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
numpy.cumsum :
5.31 ms ± 5.11 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
numpy.cumsum, edge handling :
8.52 ms ± 11.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Pandas rolling average :
9.85 ms ± 9.63 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
bottleneck.move_mean :
1.3 ms ± 12.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Numpy array rolling :
31.3 ms ± 91.9 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
Numpy array rolling, edge handling :
61.1 ms ± 55.9 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
Zamanlama, Büyük pencere (n = 1001)
Direct "for" loop :
4.67 s ± 34 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
List comprehension :
4.46 s ± 14.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
scipy.convolve :
103 ms ± 165 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
scipy.convolve, edge handling :
272 ms ± 1.23 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
numpy.cumsum :
5.19 ms ± 12.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
numpy.cumsum, edge handling :
8.7 ms ± 11.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Pandas rolling average :
9.67 ms ± 199 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
bottleneck.move_mean :
1.31 ms ± 15.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Bellek, Küçük pencere (n = 3)
The memory_profiler extension is already loaded. To reload it, use:
%reload_ext memory_profiler
scipy.convolve :
peak memory: 362.66 MiB, increment: 73.61 MiB
scipy.convolve, edge handling :
peak memory: 510.24 MiB, increment: 221.19 MiB
numpy.cumsum :
peak memory: 441.81 MiB, increment: 152.76 MiB
numpy.cumsum, edge handling :
peak memory: 518.14 MiB, increment: 228.84 MiB
Pandas rolling average :
peak memory: 449.34 MiB, increment: 160.02 MiB
bottleneck.move_mean :
peak memory: 374.17 MiB, increment: 75.54 MiB
Numpy array rolling :
peak memory: 661.29 MiB, increment: 362.65 MiB
Numpy array rolling, edge handling :
peak memory: 1111.25 MiB, increment: 812.61 MiB
Bellek, Büyük pencere (n = 1001)
scipy.convolve :
peak memory: 370.62 MiB, increment: 71.83 MiB
scipy.convolve, edge handling :
peak memory: 521.98 MiB, increment: 223.18 MiB
numpy.cumsum :
peak memory: 451.32 MiB, increment: 152.52 MiB
numpy.cumsum, edge handling :
peak memory: 527.51 MiB, increment: 228.71 MiB
Pandas rolling average :
peak memory: 451.25 MiB, increment: 152.50 MiB
bottleneck.move_mean :
peak memory: 374.64 MiB, increment: 75.85 MiB
Pandaların kullanıldığı bu cevap, rolling_mean
artık Pandaların bir parçası olmadığı için yukarıdan uyarlanmıştır.
# the recommended syntax to import pandas
import pandas as pd
import numpy as np
# prepare some fake data:
# the date-time indices:
t = pd.date_range('1/1/2010', '12/31/2012', freq='D')
# the data:
x = np.arange(0, t.shape[0])
# combine the data & index into a Pandas 'Series' object
D = pd.Series(x, t)
Şimdi, rolling
aşağıdaki örneğimde 10 gün olan bir pencere boyutuyla veri çerçevesindeki işlevi çağırın .
d_mva10 = D.rolling(10).mean()
# d_mva is the same size as the original Series
# though obviously the first w values are NaN where w is the window size
d_mva10[:11]
2010-01-01 NaN
2010-01-02 NaN
2010-01-03 NaN
2010-01-04 NaN
2010-01-05 NaN
2010-01-06 NaN
2010-01-07 NaN
2010-01-08 NaN
2010-01-09 NaN
2010-01-10 4.5
2010-01-11 5.5
Freq: D, dtype: float64
Darboğaz kullanılarak bunun kolayca çözülebileceğini düşünüyorum
Aşağıdaki temel örneğe bakın:
import numpy as np
import bottleneck as bn
a = np.random.randint(4, 1000, size=(5, 7))
mm = bn.move_mean(a, window=2, min_count=1)
Bu, her eksen boyunca hareket ortalamasını verir.
"mm", "a" için hareketli ortalamadır.
"pencere", hareketli ortalama için dikkate alınacak maksimum girdi sayısıdır.
"min_count" hareketli ortalama için dikkate alınacak minimum girdi sayısıdır (örneğin, ilk öğe için veya dizinin nan değerleri varsa).
İşin iyi yanı, Darboğaz'ın nan değerleriyle başa çıkmaya yardımcı olması ve aynı zamanda çok verimli olması.
Kenar koşullarını dikkatli bir şekilde dikkate almak istemeniz durumunda ( ortalamayı yalnızca kenarlardaki mevcut öğelerden hesaplayın ), aşağıdaki işlev işe yarayacaktır.
import numpy as np
def running_mean(x, N):
out = np.zeros_like(x, dtype=np.float64)
dim_len = x.shape[0]
for i in range(dim_len):
if N%2 == 0:
a, b = i - (N-1)//2, i + (N-1)//2 + 2
else:
a, b = i - (N-1)//2, i + (N-1)//2 + 1
#cap indices to min and max indices
a = max(0, a)
b = min(dim_len, b)
out[i] = np.mean(x[a:b])
return out
>>> running_mean(np.array([1,2,3,4]), 2)
array([1.5, 2.5, 3.5, 4. ])
>>> running_mean(np.array([1,2,3,4]), 3)
array([1.5, 2. , 3. , 3.5])
for i in range(len(Data)):
Data[i, 1] = Data[i-lookback:i, 0].sum() / lookback
Bu kod parçasını deneyin. Bence daha basit ve işi yapıyor. yeniden inceleme, hareketli ortalamanın penceresidir.
In Data[i-lookback:i, 0].sum()
ben koydum 0
veri kümesinin ilk sütuna başvurmak için ancak birden fazla sütuna sahip durumda istediğiniz herhangi bir sütun koyabilirsiniz.
Aslında kabul edilen cevaptan biraz farklı bir davranış istedim. Bir sklearn
boru hattı için hareketli ortalama özellik çıkarıcı oluşturuyordum , bu nedenle hareketli ortalamanın çıktısının girdi ile aynı boyuta sahip olmasını istedim. İstediğim şey hareketli ortalamanın serinin sabit kaldığını varsayması, yani [1,2,3,4,5]
pencere 2 ile hareketli bir ortalama verecektir [1.5,2.5,3.5,4.5,5.0]
.
Sütun vektörleri için (kullanım durumum)
def moving_average_col(X, n):
z2 = np.cumsum(np.pad(X, ((n,0),(0,0)), 'constant', constant_values=0), axis=0)
z1 = np.cumsum(np.pad(X, ((0,n),(0,0)), 'constant', constant_values=X[-1]), axis=0)
return (z1-z2)[(n-1):-1]/n
Ve diziler için
def moving_average_array(X, n):
z2 = np.cumsum(np.pad(X, (n,0), 'constant', constant_values=0))
z1 = np.cumsum(np.pad(X, (0,n), 'constant', constant_values=X[-1]))
return (z1-z2)[(n-1):-1]/n
Tabii ki, dolgu için sabit değerler varsaymak zorunda değilsiniz, ancak bunu yapmak çoğu durumda yeterli olmalıdır.
talib , basit bir hareketli ortalama aracı ve diğer benzer ortalama alma araçlarını (yani üstel hareketli ortalama) içerir. Aşağıda, yöntemi diğer bazı çözümlerle karşılaştırmaktadır.
%timeit pd.Series(np.arange(100000)).rolling(3).mean()
2.53 ms ± 40.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit talib.SMA(real = np.arange(100000.), timeperiod = 3)
348 µs ± 3.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit moving_average(np.arange(100000))
638 µs ± 45.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Bir uyarı, gerçeğin unsurlarına sahip olması gerektiğidir dtype = float
. Aksi takdirde aşağıdaki hata ortaya çıkar
İstisna: gerçek çift değildir
İşte numba kullanan hızlı bir uygulama (türlere dikkat edin). Değiştirildiği yerde nans içerdiğini unutmayın.
import numpy as np
import numba as nb
@nb.jit(nb.float64[:](nb.float64[:],nb.int64),
fastmath=True,nopython=True)
def moving_average( array, window ):
ret = np.cumsum(array)
ret[window:] = ret[window:] - ret[:-window]
ma = ret[window - 1:] / window
n = np.empty(window-1); n.fill(np.nan)
return np.concatenate((n.ravel(), ma.ravel()))
hareketli ortalama
i'deki diziyi tersine çevirin ve i'den n'ye ortalamayı alın.
anında mini diziler oluşturmak için liste anlama özelliğini kullanın.
x = np.random.randint(10, size=20)
def moving_average(arr, n):
return [ (arr[:i+1][::-1][:n]).mean() for i, ele in enumerate(arr) ]
n = 5
moving_average(x, n)
Ya kabul edilen cevabın çözümünü, girdi olarak çıktı olarak aynı uzunluğa sahip olacak şekilde biraz değiştirilmiş ya da pandas
başka bir cevabın yorumunda belirtildiği gibi 'versiyonunu kullanıyorum. Her ikisini de gelecekte referans olması için tekrarlanabilir bir örnekle özetliyorum:
import numpy as np
import pandas as pd
def moving_average(a, n):
ret = np.cumsum(a, dtype=float)
ret[n:] = ret[n:] - ret[:-n]
return ret / n
def moving_average_centered(a, n):
return pd.Series(a).rolling(window=n, center=True).mean().to_numpy()
A = [0, 0, 1, 2, 4, 5, 4]
print(moving_average(A, 3))
# [0. 0. 0.33333333 1. 2.33333333 3.66666667 4.33333333]
print(moving_average_centered(A, 3))
# [nan 0.33333333 1. 2.33333333 3.66666667 4.33333333 nan ]
Aşağıdaki çözümü, cumsum of numpy kullanan çözümle karşılaştırarak, Bu neredeyse yarısı kadar zaman alıyor . Bunun nedeni, cumsum yapmak için tüm diziyi gözden geçirmesi ve ardından tüm çıkarma işlemini yapması gerekmemesidir. Dahası, dizi çok büyükse ve sayı çok büyükse ( olası taşma ) , cumsum " tehlikeli " olabilir . Tabii ki, burada da tehlike mevcuttur, ancak en azından yalnızca temel sayılar toplanır.
def moving_average(array_numbers, n):
if n > len(array_numbers):
return []
temp_sum = sum(array_numbers[:n])
averages = [temp_sum / float(n)]
for first_index, item in enumerate(array_numbers[n:]):
temp_sum += item - array_numbers[first_index]
averages.append(temp_sum / float(n))
return averages