Wie berechnet man den gleitenden / gleitenden Durchschnitt mit Python + NumPy / SciPy?

Lesezeit: 16 Minuten

Benutzer-Avatar
Schleifenbiene

Es scheint keine Funktion zu geben, die einfach den gleitenden Durchschnitt auf numpy/scipy berechnet, was zu verworrenen Lösungen führt.

Meine Frage ist zweigeteilt:

  • Was ist der einfachste Weg, einen gleitenden Durchschnitt mit numpy (richtig) zu implementieren?
  • Da dies nicht trivial und fehleranfällig erscheint, gibt es einen guten Grund, das nicht zu haben Batterien enthalten in diesem Fall?

  • Die Faltungslösung scheint mir nicht so kompliziert zu sein!

    – Wim

    14. Januar 2013 um 5:29 Uhr

  • Ist ein gleitender Durchschnitt nicht nur ein Tiefpassfilter (dh „Unschärfe“)? Ich bin mir ziemlich sicher, dass das genau das ist, wofür Faltung gedacht ist …

    – Benutzer541686

    14. Januar 2013 um 7:20 Uhr


  • @mmgp Ich glaube, ich hatte gehofft, falsch zu liegen, oder dass es einen guten, offensichtlichen Grund gab.

    – Schleifenbiene

    14. Januar 2013 um 19:55 Uhr

  • @wim Es war halb als Wortspiel gemeint. Aber die bloße Tatsache, dass die Frage existiert, bedeutet, dass es nicht einfach ist, einen gleitenden Durchschnitt aus numpy.convolute zu erstellen.

    – Schleifenbiene

    14. Januar 2013 um 19:56 Uhr

  • Mögliches Duplikat von Moving Average oder Running Mean

    – pp

    5. März 2020 um 23:15 Uhr


Benutzer-Avatar
Jaime

Wenn Sie nur einen einfachen, nicht gewichteten gleitenden Durchschnitt wünschen, können Sie ihn einfach implementieren np.cumsumdie vielleicht ist schneller als FFT-basierte Methoden:

BEARBEITEN Korrigierte eine Off-by-One-Falschindizierung, die von Bean im Code entdeckt wurde. BEARBEITEN

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])

Ich denke also, die Antwort lautet: Es ist wirklich einfach zu implementieren, und vielleicht ist numpy schon ein wenig mit spezialisierten Funktionen aufgebläht.

  • Dieser Code ist falsch. zB Moving_Average ([1,2,5,10]n=2) ergibt [ 1. , 3.5, 8.5]. Sogar der Testfall des Antwortenden für einen gleitenden Durchschnitt von Werten von 0 bis 19 ist falsch und behauptet, dass der Durchschnitt von 0, 1 und 2 0,5 ist. Wie hat es 6 Upvotes bekommen?

    – Jeremy Kun

    22. August 2013 um 18:18 Uhr


  • Danke für die Fehlerüberprüfung, es scheint jetzt zu funktionieren. Was die Upvotes angeht, vermute ich, dass die allgemeine Idee hinter der Antwort stärker gewichtet wurde als ein Off-by-One-Fehler in der Implementierung, aber wer weiß.

    – Jaime

    22. August 2013 um 19:33 Uhr

  • Ich habe das Problem gefunden. ret[n:] -= ret[:-n] ist NICHT DAS GLEICHE wie ret[n:] = ret[n:] - ret[:-n]. Ich habe den Code in dieser Antwort behoben. Edit: Nein, jemand anderes ist mir gerade zuvorgekommen.

    – Timmm

    4. Dezember 2013 um 14:29 Uhr


  • @Timmmm habe ich, das war in der Tat das Problem. Das allgemeine Prinzip hinter dieser Antwort wird häufig in der Bildverarbeitung verwendet (summierte Bereichstabellen, die sie es nennen), daher musste das Problem in der Implementierung liegen. Ein gutes Beispiel für vorzeitige Optimierung, da ich mich irgendwie daran erinnere, die Operation an Ort und Stelle durchgeführt zu haben, “weil sie effizienter ist”. Auf der positiven Seite hat es wahrscheinlich schneller die falsche Antwort produziert …

    – Jaime

    4. Dezember 2013 um 14:39 Uhr

  • Hmmm, es scheint, dass diese “einfach zu implementierende” Funktion eigentlich ziemlich leicht falsch zu machen ist und eine gute Diskussion über Speichereffizienz gefördert hat. Ich bin froh, aufgebläht zu sein, wenn es bedeutet zu wissen, dass etwas richtig gemacht wurde.

    – Richard

    20. September 2014 um 19:23 Uhr

Benutzer-Avatar
jatu

Eine einfache Möglichkeit, dies zu erreichen, ist die Verwendung von np.convolve. Die Idee dahinter ist, die Art und Weise zu nutzen, wie die diskrete Faltung berechnet und verwenden Sie es, um a zurückzugeben rollendes Mittel. Dies kann durch Faltung mit einer Folge von erfolgen np.ones einer Länge, die der gewünschten Schiebefensterlänge entspricht.

Dazu könnten wir folgende Funktion definieren:

def moving_average(x, w):
    return np.convolve(x, np.ones(w), 'valid') / w

Diese Funktion nimmt die Faltung der Sequenz x und eine Folge von Einsen der Länge w. Beachten Sie, dass die gewählte mode ist valid so dass das Faltungsprodukt nur für Punkte gegeben ist, an denen sich die Sequenzen vollständig überlappen.


Einige Beispiele:

x = np.array([5,3,8,10,2,1,5,1,0,2])

Für einen gleitenden Durchschnitt mit einem Längenfenster 2 Wir würden haben:

moving_average(x, 2)
# array([4. , 5.5, 9. , 6. , 1.5, 3. , 3. , 0.5, 1. ])

Und für ein Fenster der Länge 4:

moving_average(x, 4)
# array([6.5 , 5.75, 5.25, 4.5 , 2.25, 1.75, 2.  ])

Wie funktioniert convolve Arbeit?

Schauen wir uns genauer an, wie die diskrete Faltung berechnet wird. Die folgende Funktion zielt darauf ab, den Weg zu replizieren np.convolve berechnet die Ausgangswerte:

def mov_avg(x, w):
    for m in range(len(x)-(w-1)):
        yield sum(np.ones(w) * x[m:m+w]) / w 

Was für das gleiche Beispiel oben auch ergeben würde:

list(mov_avg(x, 2))
# [4.0, 5.5, 9.0, 6.0, 1.5, 3.0, 3.0, 0.5, 1.0]

Was also bei jedem Schritt getan wird, ist das innere Produkt zwischen der Reihe von Einsen und dem Strom zu bilden Fenster. In diesem Fall die Multiplikation mit np.ones(w) ist überflüssig, da wir direkt die nehmen sum der Folge.

Unten ist ein Beispiel dafür, wie die ersten Ausgaben berechnet werden, damit es etwas klarer ist. Nehmen wir an, wir wollen ein Fenster von 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

Und die folgende Ausgabe würde wie folgt berechnet:

  [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

Und so weiter, wobei ein gleitender Durchschnitt der Sequenz zurückgegeben wird, sobald alle Überlappungen durchgeführt wurden.

  • Das ist eine schöne Idee! Es ist schneller als die Antwort von @Jaime für kleine n, wird aber für größere n langsamer.

    – Felipe Gerhard

    7. Mai 2019 um 14:06 Uhr

  • Manchmal ist es nützlich, wenn das Ausgabe-Array die gleiche Größe wie die Eingabe hat. Dafür die mode='valid' kann ersetzt werden durch 'same'. Gerade in diesem Fall werden Kantenpunkte gegen Null gravitieren.

    – Ilia Barahovsky

    1. März 2020 um 20:31 Uhr

  • Wie erhalten Sie in einer Situation, in der einige Elemente des Arrays „x“ der Funktion „Keine“ oder „Null“ sein können, die entsprechenden „x“-Werte der von dieser Funktion zurückgegebenen Werte? Die Größe des von dieser Funktion zurückgegebenen Arrays kann kleiner sein als das ihr zugeführte Array ‘x’.

    – Sonnenbär

    24. August 2020 um 16:45 Uhr

  • Sollte klargestellt werden, dass diese Methode den „zentrierten gleitenden Durchschnitt“ anstelle des „einfachen gleitenden Durchschnitts“ ergeben würde, der häufig für Finanzanwendungen berechnet wird? en.wikipedia.org/wiki/Moving_average

    – WilderField

    4. Mai 2021 um 2:43 Uhr

  • Eigentlich machen Sie nur ein durchschnittliches Pooling mit Stride = 1, keine tatsächliche Faltung.

    – Anonym

    8. Juni um 23:45 Uhr


Benutzer-Avatar
Teig

Das Fehlen einer bestimmten domänenspezifischen Funktion von NumPy ist möglicherweise auf die Disziplin und Treue des Kernteams zu NumPys Hauptrichtlinie zurückzuführen: Stellen Sie einen N-dimensionalen Array-Typ bereit, sowie Funktionen zum Erstellen und Indizieren dieser Arrays. Wie viele grundlegende Ziele ist dieses nicht klein, und NumPy macht es brillant.

Die (viel) größer SciPy enthält eine viel größere Sammlung domänenspezifischer Bibliotheken (sog Unterpakete von SciPy-Entwicklern) – zum Beispiel numerische Optimierung (optimieren), Signalverarbeitung (Signal) und Integralrechnung (integrieren).

Ich vermute, dass die Funktion, nach der Sie suchen, in mindestens einem der SciPy-Unterpakete enthalten ist (scipy.signal vielleicht); Ich würde jedoch zuerst in der Sammlung nachsehen SciPy-Scikitsidentifizieren Sie das/die relevante(n) Scikit(s) und suchen Sie dort nach der interessierenden Funktion.

Scikits sind unabhängig entwickelte Pakete, die auf NumPy/SciPy basieren und auf eine bestimmte technische Disziplin ausgerichtet sind (z. Scikits-Bild, scikits-lernenetc.) Einige davon waren (insbesondere die awesome OpenOpt für die numerische Optimierung) waren hoch angesehene, ausgereifte Projekte, lange bevor sie sich entschieden, unter den relativ neuen zu residieren scikits Rubrik. Das Scikits Homepage gemocht oben listet etwa 30 solcher auf scikitsobwohl zumindest einige davon nicht mehr aktiv entwickelt werden.

Wenn Sie diesen Rat befolgen, werden Sie dazu geführt scikits-Zeitreihe; dieses Paket befindet sich jedoch nicht mehr in aktiver Entwicklung; In der Tat, Pandas geworden ist, AFAIK, die de facto NumPy-basierte Zeitreihenbibliothek.

Pandas verfügt über mehrere Funktionen, die zur Berechnung von a verwendet werden können gleitender Durchschnitt; die einfachste davon ist wahrscheinlich rollende_Mitteldie Sie so verwenden:

>>> # 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)

Rufen Sie jetzt einfach die Funktion auf rollende_Mittel Übergabe des Series-Objekts und a Fenstergrößewas in meinem Beispiel unten ist 10 Tage.

>>> 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

Überprüfen Sie, ob es funktioniert hat – vergleichen Sie z. B. die Werte 10–15 in der ursprünglichen Reihe mit der neuen Reihe, die mit dem gleitenden Mittelwert geglättet wurde

>>> 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

Die Funktion rolling_mean, zusammen mit etwa einem Dutzend anderer Funktionen, sind in der Pandas-Dokumentation informell unter der Rubrik zusammengefasst bewegliches Fenster Funktionen; eine zweite, verwandte Gruppe von Funktionen in Pandas wird als exponentiell gewichtete Funktionen bezeichnet (z. B. ewma, der den exponentiell gleitenden gewichteten Durchschnitt berechnet). Die Tatsache, dass diese zweite Gruppe nicht in der ersten enthalten ist (bewegliches Fenster Funktionen) liegt vielleicht daran, dass die exponentiell gewichteten Transformationen nicht auf ein Fenster mit fester Länge angewiesen sind

  • Pandas hat eine starke Reihe von beweglichen Fensterfunktionen. Aber es scheint mir ein wenig zu viel Aufwand für einen einfachen gleitenden Durchschnitt zu sein.

    – Jaime

    14. Januar 2013 um 7:31 Uhr


  • Nun, ich bezweifle, dass die Berechnung eines gleitenden Durchschnitts eine isolierte Anforderung für das OP oder für fast jeden anderen ist. Wenn Sie einen gleitenden Durchschnitt berechnen müssen, haben Sie mit ziemlicher Sicherheit eine Zeitreihe, was bedeutet, dass Sie eine Datenstruktur benötigen, die es Ihnen ermöglicht, einen Datum-Uhrzeit-Index an Ihre Daten anzupassen, und das ist der „Overhead“, auf den Sie sich beziehen.

    – Teig

    14. Januar 2013 um 7:45 Uhr

  • Zunächst einmal vielen Dank, dass Sie sich die Zeit genommen haben, diese äußerst informative Antwort zu schreiben. In der Tat sehe ich keinen Nutzen für einen gleitenden Durchschnitt, der keine Zeitreihe beinhaltet. Aber das bedeutet nicht, dass man es an eine Datumszeit oder sogar an ein bestimmtes Abtastintervall anpassen muss (es kann unbekannt sein).

    – Schleifenbiene

    14. Januar 2013 um 20:02 Uhr


  • Ich wollte nur hinzufügen, dass die gleitende Durchschnittsfunktion in die extrahiert wurde Engpass Bibliothek, wenn Pandas als Abhängigkeit zu schwergewichtig erscheint.

    – Roboterchat

    16. Juli 2014 um 12:38 Uhr


  • ‘rolling_mean’ ist kein Teil von Pandas mehr, bitte sehen Sie sich stattdessen die Antwort mit ‘rolling’ an

    – Vladtn

    16. Dezember 2018 um 17:28 Uhr

Benutzer-Avatar
argentum2f

Hier sind eine Vielzahl von Möglichkeiten, dies zu tun, zusammen mit einigen Benchmarks. Die besten Methoden sind Versionen, die optimierten Code aus anderen Bibliotheken verwenden. Das bottleneck.move_mean Methode ist wahrscheinlich rundum am besten. Das scipy.convolve Der Ansatz ist auch sehr schnell, erweiterbar und syntaktisch und konzeptionell einfach, lässt sich aber nicht gut für sehr große Fensterwerte skalieren. Das numpy.cumsum Methode ist gut, wenn Sie eine reine brauchen numpy sich nähern.

Notiz: Einige davon (zB bottleneck.move_mean) sind nicht zentriert und verschieben Ihre Daten.

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 https://stackoverflow.com/questions/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)

Timing, kleines Fenster (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)

Timing, großes Fenster (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)

Speicher, kleines Fenster (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

Speicher, großes Fenster (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

Ab in Numpy 1.20das sliding_window_view bietet eine Möglichkeit, durch Fenster von Elementen zu gleiten/rollen. Fenster, die Sie dann individuell mitteln können.

Zum Beispiel für a 4-Elementfenster:

from numpy.lib.stride_tricks import sliding_window_view

# values = np.array([5, 3, 8, 10, 2, 1, 5, 1, 0, 2])
np.average(sliding_window_view(values, window_shape = 4), axis=1)
# array([6.5, 5.75, 5.25, 4.5, 2.25, 1.75, 2])

Beachten Sie das Zwischenergebnis von sliding_window_view:

# values = np.array([5, 3, 8, 10, 2, 1, 5, 1, 0, 2])
sliding_window_view(values, window_shape = 4)
# array([[ 5,  3,  8, 10],
#        [ 3,  8, 10,  2],
#        [ 8, 10,  2,  1],
#        [10,  2,  1,  5],
#        [ 2,  1,  5,  1],
#        [ 1,  5,  1,  0],
#        [ 5,  1,  0,  2]])

Benutzer-Avatar
Vladtn

Diese Antwort mit Pandas wird von oben angepasst, wie rolling_mean ist nicht mehr Teil von Pandas

# 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)

Rufen Sie jetzt einfach die Funktion auf rolling auf dem Datenrahmen mit einer Fenstergröße, die in meinem Beispiel unten 10 Tage beträgt.

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

Benutzer-Avatar
Anthony Anyanwu

Ich denke, dass dies leicht gelöst werden kann mit Engpass

Siehe einfaches Beispiel unten:

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)

Dies ergibt einen Bewegungsmittelwert entlang jeder Achse.

  • “mm” ist der gleitende Mittelwert für “a”.

  • “Fenster” ist die maximale Anzahl von Einträgen, die für den gleitenden Mittelwert berücksichtigt werden.

  • “min_count” ist die minimale Anzahl von Einträgen, die für den gleitenden Mittelwert zu berücksichtigen sind (z. B. für das erste Element oder wenn das Array nan-Werte hat).

Das Gute daran ist, dass Bottleneck hilft, mit Nan-Werten umzugehen, und es ist auch sehr effizient.

  • Bottleneck ist eine schöne, schnell und einfach zu implementierende Lösung (Upvote), aber es ist gut zu betonen, dass es nur “verzögerte” Laufmittel bietet, nicht zentriert, wie auch von argentum2f hervorgehoben

    – Adrian Tompkins

    29. September 2021 um 7:28 Uhr

1019830cookie-checkWie berechnet man den gleitenden / gleitenden Durchschnitt mit Python + NumPy / SciPy?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy