Python, Pandas und Zeitserien

Einführung

Time Series Pandas

In unserem nächsten Kapitel des Pandas-Tutorial behandeln wir Time Series. Eine Time Series ist eine Reihe von Datenpunkten, welche in chronologischer (zeitlicher) Reihenfolge gelistet (indiziert) sind. Für gewöhnlich ist eine Time Series eine Sequenz von Werten, mit gleichen zeitlichen Abständen.

Alle gemessenen Daten, die auch mit einem bestimmten Zeitpunkt in Verbindung stehen, können als Time Series angesehen werden. Messungen können durchaus unregelmäßig sein, haben aber in den meisten Fällen eine feste Frequenz bzw. Regelmässigkeit. D.h. dass Daten bspw. alle 5 Millisekunden, alle 10 Sekunden oder jede Stunde erhoben werden. Time Series werden oft in Liniencharts dargestellt.

Bevor Sie fortfahren möchten wir ihnen noch unser Tutorial empfehlen zum Thema Time Processing mit Standard Python-Modulen, wie z.B. datetime, time und calendar.

Wir wollen in diesem Kapitel die Pandas-Tools vorstellen um mit Time Series umzugehen. Sie werden also lernen mit grossen Time Series zu arbeiten und diese zu modifizieren:

Zeitreihen und Python

Wir könnten eine Pandas Series definieren, welche als Index eine Reihe von Zeitstempeln enthält.

import numpy as np
import pandas as pd
from datetime import datetime, timedelta as delta
ndays = 10
start = datetime(2018, 12, 1)
dates = [start - delta(days = x) for x in range(0, ndays)]
values = [25, 50, 15, 67, 70, 9, 28, 30, 32, 12]
ts = pd.Series(values, index = dates)
ts
Der obige Code führt zu folgendem Ergebnis:
2018-12-01    25
2018-11-30    50
2018-11-29    15
2018-11-28    67
2018-11-27    70
2018-11-26     9
2018-11-25    28
2018-11-24    30
2018-11-23    32
2018-11-22    12
dtype: int64

Wir ermitteln den Typ der soeben erstellen Time-Series:

type(ts)
Führt man obigen Code aus, erhält man folgende Ausgabe:
pandas.core.series.Series

Was wir erzeugt haben ist eine Zeitreihe oder Time-Series, weil es auf den Series von Pandas basiert. Wie sieht der Index dieser Time-Series aus? Wir sehen es hier:

ts.index
Der obige Code liefert folgendes Ergebnis:
DatetimeIndex(['2018-12-01', '2018-11-30', '2018-11-29', '2018-11-28',
               '2018-11-27', '2018-11-26', '2018-11-25', '2018-11-24',
               '2018-11-23', '2018-11-22'],
              dtype='datetime64[ns]', freq=None)

Wir erstellen eine weitere Time-Series:

values2 = [32, 54, 18, 61, 72, 19, 21, 33, 29, 17]
ts2 = pd.Series(values2, index=dates)

Es ist möglich arithmetische Operationen auf Zeitreihen durchzuführen, wie bei anderen Series-Objekten auch. Als Beispiel addieren wir die beiden zuvor erstellten Time-Series:

ts + ts2
Wir können die folgenden Ergebnisse erwarten, wenn wir den obigen Python-Code ausführen:
2018-12-01     57
2018-11-30    104
2018-11-29     33
2018-11-28    128
2018-11-27    142
2018-11-26     28
2018-11-25     49
2018-11-24     63
2018-11-23     61
2018-11-22     29
dtype: int64

Arithmetischer Durchschnitt der beiden Series-Objekte:

(ts + ts2) / 2
Führt man obigen Code aus, erhält man folgende Ausgabe:
2018-12-01    28.5
2018-11-30    52.0
2018-11-29    16.5
2018-11-28    64.0
2018-11-27    71.0
2018-11-26    14.0
2018-11-25    24.5
2018-11-24    31.5
2018-11-23    30.5
2018-11-22    14.5
dtype: float64

Dies kann auch mit Series-Objekten gemacht werden, die eine andere Indexierung haben.

import pandas as pd
from datetime import datetime, timedelta as delta
ndays = 10
start = datetime(2018, 6, 1)
dates = [start - delta(days=x) for x in range(0, ndays)]
start2 = datetime(2018, 5, 28)
dates2 = [start2 - delta(days=x) for x in range(0, ndays)]
values = [25, 50, 15, 67, 70, 9, 28, 30, 32, 12]
values2 = [32, 54, 18, 61, 72, 19, 21, 33, 29, 17]
ts = pd.Series(values, index = dates)
ts2 = pd.Series(values2, index = dates2)
ts + ts2
Der obige Python-Code liefert folgendes Ergebnis:
2018-05-19      NaN
2018-05-20      NaN
2018-05-21      NaN
2018-05-22      NaN
2018-05-23     31.0
2018-05-24    104.0
2018-05-25     91.0
2018-05-26     46.0
2018-05-27     63.0
2018-05-28    102.0
2018-05-29      NaN
2018-05-30      NaN
2018-05-31      NaN
2018-06-01      NaN
dtype: float64

Erstellen von Date-Ranges

Die Methode date_range() aus dem Pandas-Modul kann für die Erstellung eines DAtumsstempel-Index verwendet werden:

import pandas as pd
index = pd.date_range('12/24/1970', '01/03/1971')
index
Führt man obigen Code aus, erhält man folgendes Ergebnis:
DatetimeIndex(['1970-12-24', '1970-12-25', '1970-12-26', '1970-12-27',
               '1970-12-28', '1970-12-29', '1970-12-30', '1970-12-31',
               '1971-01-01', '1971-01-02', '1971-01-03'],
              dtype='datetime64[ns]', freq='D')

Wir haben ein Start- und ein Ende-Datum an die date_range()-Methode übergeben. Ebenso ist es möglich nur einen Start oder nur ein Ende zu übergeben. In diesem Fall muss jedoch die Anzahl der Perioden, über den Schlüsselwort-Parameter periods, angegeben werden:

index = pd.date_range(start='12/24/1970', periods=7)
print(index)
DatetimeIndex(['1970-12-24', '1970-12-25', '1970-12-26', '1970-12-27',
               '1970-12-28', '1970-12-29', '1970-12-30'],
              dtype='datetime64[ns]', freq='D')
index = pd.date_range(end='12/24/1970', periods=7)
print(index)
DatetimeIndex(['1970-12-18', '1970-12-19', '1970-12-20', '1970-12-21',
               '1970-12-22', '1970-12-23', '1970-12-24'],
              dtype='datetime64[ns]', freq='D')

Ebenso ist es möglich Zeitreihen zu erstellen, welche nur die Arbeitstage beinhalten. Dazu muss der Schlüsselwort-Paremter freq auf B gesetzt werden:

index = pd.date_range('2017-04-07', '2017-04-13', freq="B")
print(index)
DatetimeIndex(['2017-04-07', '2017-04-10', '2017-04-11', '2017-04-12',
               '2017-04-13'],
              dtype='datetime64[ns]', freq='B')

Im nächsten Beispiel generieren wir eine Zeitreihe, welche die Monatsenden zwischen zwei Zeitpunkten enthält. Dabei sehen wir, dass das Jahr 2016 den 29. Februar hatte, weil es ein Schaltjahr war:

index = pd.date_range('2016-02-25', '2016-07-02', freq="M")
index
Führt man obigen Code aus, erhält man folgendes Ergebnis:
DatetimeIndex(['2016-02-29', '2016-03-31', '2016-04-30', '2016-05-31',
               '2016-06-30'],
              dtype='datetime64[ns]', freq='M')

Weitere Abkürzungen:

Alias Description
B business day frequency
C custom business day frequency (experimental)
D calendar day frequency
W weekly frequency
M month end frequency
BM business month end frequency
MS month start frequency
BMS business month start frequency
Q quarter end frequency
BQ business quarter endfrequency
QS quarter start frequency
BQS business quarter start frequency
A year end frequency
BA business year end frequency
AS year start frequency
BAS business year start frequency
H hourly frequency
T minutely frequency
S secondly frequency
L milliseonds
U microseconds
index = pd.date_range('2017-02-05', '2017-04-13', freq="W-Mon")
index
Der obige Python-Code liefert folgendes Ergebnis:
DatetimeIndex(['2017-02-06', '2017-02-13', '2017-02-20', '2017-02-27',
               '2017-03-06', '2017-03-13', '2017-03-20', '2017-03-27',
               '2017-04-03', '2017-04-10'],
              dtype='datetime64[ns]', freq='W-MON')