Gleitende Durchschnitte mit Python berechnen

Eine Bedarfskurve kann auf vier verschiedene Arten verlaufen: Sporadisch (unvorhersehbar), konstant (selbes Niveau), trendmäßig (steigend oder fallend) und saisonal (steigende und fallende Bereiche).

Verschiedene Arten von Bedarfsverläufe
Verschiedene Arten von Bedarfsverläufen

Konstantes Niveau

Bei einem konstanten Bedarf schwanken die Werte einer Zeitreihe unregelmäßig um ein konstantes Niveau. Es bieten sich zwei Instrumente zur Berechnung eines Prognosewertes an, den gleitenden Durchschnitt und die exponentielle Glättung erster Ordnung.

Der gleitende Durchschnitt errechnet sich ähnlich wie der normale Mittelwert:

\[{\frac {1}{n}}\sum _{i=1}^{n}{x_{i}}={\frac {x_{1}+x_{2}+\cdots +x_{n}}{n}}\]

oder

\[\hat{y}_{t+1} = \frac{1}{T}\sum^{t}_{\tau=t-T+1} y_t\]

Die Werte, aus denen der Mittelwert gebildet werden soll, werden addiert und die Summe wiederum durch die Anzahl der Werte geteilt. Die in die Prognose einbezogenen Vergangenheitswerte erhalten dieselbe Gewichtung.

Problematiken

Während eine große Menge an Werten generell vorteilhaft ist, um Ausreißer herauszufiltern, ist dies bei der Bedarfsermittlung eher von Nachteil, da auch Vorperioden betrachtet werden in denen das Unternehmen anders ausgerichtet war oder einen geringeren Marktanteil hatte.

Beispiel mit Python

import pandas as pd
import numpy as np
df = pd.read_csv('../data/gleitende_durchschnitt/duschgel.csv',  sep = ';' ,decimal = ',', header = None )
df.columns = ['A', 'B']
df
AB
01106.8
12129.2
23153.0
34149.1
45158.3
56132.9
67149.8
78140.3
89138.3
910152.2
1011128.1

Man berechnet den Mittelwert, indem man die Summe der betrachteten Zahlen durch ihre Anzahl teilt.

GD = (106.8 + 129.2 + 153.0) / 3
np.round(GD,1)
129.7

Um dies zu implementieren, wird die iloc-Funktion von Pandas verwendet. Die Position der Bedarfsspalte wird in der iloc-Funktion festgelegt. Während die Zeile eine Variable i ist, welche solange iteriert, bis das Ende des Datenframe erreicht wird. Greife selektiv auf die Zeile 0 zu. Dazu verwende den Locator iloc. loc ruft Zeilen (und/oder Spalten) mit bestimmten Bezeichnungen ab. iloc holt Zeilen (und/oder Spalten) an ganzzahligen Positionen. Siehe: https://stackoverflow.com/questions/31593201/how-are-iloc-and-loc-different

df.iloc[0]
A      1.0
B    106.8
Name: 0, dtype: float64
x1 = df.iloc[0,1]
print(x1)
x2 = df.iloc[1,1]
print(x2)
x3 = df.iloc[2,1]
print(x3)
106.8
129.2
153.0
df.loc[df.index[0 + 2]]
A      3.0
B    153.0
Name: 2, dtype: float64
for x in range(0,df.shape[0]-2):
    df.loc[df.index[x + 2], 'GD_3'] = np.round(((df.iloc[x, 1] + df.iloc[x + 1, 1] + df.iloc[x + 2, 1]) /3), 1)
df
ABGD_3
01106.8NaN
12129.2NaN
23153.0129.7
34149.1143.8
45158.3153.5
56132.9146.8
67149.8147.0
78140.3141.0
89138.3142.8
910152.2143.6
1011128.1139.5
import matplotlib.pyplot as plt
%matplotlib inline
import matplotlib.style as style
style.use('fivethirtyeight')
plt.figure(figsize=[15,10])
plt.grid(True)
plt.plot(df['B'],label='Bedarf',color='#30e67f')
plt.plot(df['GD_3'],label='GD T=3',color='#533E2D')
plt.legend(loc=2)
<matplotlib.legend.Legend at 0x269d286c0c8>


png

Überprüfung der Ergebnisse

Wir überprüfen unser Vorgehen mit der eingebauten pandas Funktion rolling.

df
ABGD_3
01106.8NaN
12129.2NaN
23153.0129.7
34149.1143.8
45158.3153.5
56132.9146.8
67149.8147.0
78140.3141.0
89138.3142.8
910152.2143.6
1011128.1139.5
df['Rolling'] = df['B'].rolling(3).mean()
df
ABGD_3Rolling
01106.8NaNNaN
12129.2NaNNaN
23153.0129.7129.666667
34149.1143.8143.766667
45158.3153.5153.466667
56132.9146.8146.766667
67149.8147.0147.000000
78140.3141.0141.000000
89138.3142.8142.800000
910152.2143.6143.600000
1011128.1139.5139.533333

Quellen: [1] https://www.ingenieurkurse.de/produktion/aggregierte-produktionsplanung/einstufige-produktionsprogrammplanung/einstufige-mehrperiodige-produktionsprogrammplanung/prognosen-zur-nachfrageentwicklung/methode-des-gleitenden-durchschnitts.html

[2] https://otexts.com/fpp2/decomposition.html

[3] https://www.cmegroup.com/education/courses/technical-analysis/understanding-moving-averages.html

[4] https://www.uni-siegen.de/smi/aktuelles/bestandsmanagement_wolf.pdf

[5] https://de.wikibooks.org/wiki/Materialwirtschaft:_Beschaffung:_Bedarfsarten_und_Bedarfsermittlung

[6] https://www.datacamp.com/community/tutorials/moving-averages-in-pandas