Python, Pandas und Time Series

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 Linien-Charts 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:

Time Series in Pandas 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, 6, 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 Python-Code liefert folgendes Ergebnis:
2018-06-01    25
2018-05-31    50
2018-05-30    15
2018-05-29    67
2018-05-28    70
2018-05-27     9
2018-05-26    28
2018-05-25    30
2018-05-24    32
2018-05-23    12
dtype: int64

Wir prüfen den Type der soeben erstellen Time Series:

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

Wie sieht der Index der Time Series aus? Wir sehen es hier:

ts.index
Führt man obigen Code aus, erhält man folgende Ausgabe:
DatetimeIndex(['2018-06-01', '2018-05-31', '2018-05-30', '2018-05-29',
               '2018-05-28', '2018-05-27', '2018-05-26', '2018-05-25',
               '2018-05-24', '2018-05-23'],
              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 die Time Series durchzuführen, wie bei anderen Series-Objekten auch. Als Beispiel addieren wir die beiden zuvor erstellten Time Series:

ts + ts2
Führt man obigen Code aus, erhält man Folgendes:
2018-06-01     57
2018-05-31    104
2018-05-30     33
2018-05-29    128
2018-05-28    142
2018-05-27     28
2018-05-26     49
2018-05-25     63
2018-05-24     61
2018-05-23     29
dtype: int64

Arithmetischer Durchschnitt von beiden Series-Objekten:

(ts + ts2) / 2
Führt man obigen Code aus, erhält man folgende Ausgabe:
2018-06-01    28.5
2018-05-31    52.0
2018-05-30    16.5
2018-05-29    64.0
2018-05-28    71.0
2018-05-27    14.0
2018-05-26    24.5
2018-05-25    31.5
2018-05-24    30.5
2018-05-23    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 Code führt zu folgendem 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 Zeitstempel-Index verwendet werden:

import pandas as pd
index = pd.date_range('12/24/1970', '01/03/1971')
index
Wir können die folgende Ausgabe erwarten, wenn wir den obigen Python-Code ausführen:
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=4)
print(index)
DatetimeIndex(['1970-12-24', '1970-12-25', '1970-12-26', '1970-12-27'], dtype='datetime64[ns]', freq='D')
index = pd.date_range(end='12/24/1970', periods=3)
print(index)
DatetimeIndex(['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 hat, weil es ein Schaltjahr war:

index = pd.date_range('2016-02-25', '2016-07-02', freq="M")
index
Wir erhalten die folgende Ergebnisse:
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
Führt man obigen Code aus, erhält man folgende Ausgabe:
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')