Zeitreihe: Geburtenzahlen

3 Minuten zum Lesen

Geburten in Quebec von 1977 bis 1990

Die Untersuchung des Verlaufs von Geburtenzahlen zeigt sehr schön, wie sich Informationen aus einer Zeitreihe gewinnen lassen, indem man ihre Variation auf verschiedenen Zeitskalen betrachtet. Der hier betrachtete Datensatz umfasst die Geburtenzahlen in Quebec in den Jahren 1977 bis 1990. Sie sind zugänglich über die Time Series Data Library.

Das Paket DataFrames wird verwendet, um die Daten bequem speichern zu können. Mit PyPlot werden die Diagramme erstellt.

import DataFrames; Df = DataFrames;
import PyPlot; Plt = PyPlot;
import CSV

Für einen ersten Überblick werden die Daten eingelesen. Die Anzahl der Geburten wird gegen die Zeit aufgetragen.

sdatfile = "/home/nepomuk/projekte/Statistik/data/Zeitreihen-2017/ndbq.csv"
tms = Df.DataFrame()
tms = CSV.read(sdatfile, delim=';')
Df.head(tms)
Datumn
11977-01-01208
21977-01-02241
31977-01-03274
41977-01-04256
51977-01-05294
61977-01-06281
nrec = size(tms)[1]
5113
vt = collect(1:nrec);
px = Plt.axes()
Plt.ylim(125,375)
px[:plot](vt, tms[:n])
px[:set_title]("Geburtenzahlen")
px[:set_ylabel]("Anzahl")
px[:set_xticks](1:365:nrec)
xlabels = [string(y) for y in 77:91]
px[:set_xticklabels](xlabels)
px[:set_xlabel]("Jahr");

Geburtenzahlen-Rohdaten

Die Daten zeigen starke Schwankungen auf einer kleinen Zeitskala.

Variation nach Wochentagen

In höherer zeitlicher Auflösung zeigt sich, dass die Anzahl der Geburten an den verschiedenen Wochentagen stark variiert. Es wird ein Zeitraum von acht Wochen in April und Mai 1979 näher betrachtet. (Der 2. April war ein Montag.)

rt = range(822, 56)
apr78 = Df.DataFrame(Tag = tms[rt, :Datum], n = tms[rt, :n]);
xv = apr78[:n]
np = size(xv, 1)
vt = collect(1:np)
px = Plt.axes()
px[:plot](vt, xv)
px[:set_title]("Geburtenzahlen April/Mai 1979")
px[:set_ylabel]("Anzahl")
nxticks = size(1:7:np)[1]
xticksminor = collect(1:np)
px[:set_xticks](xticksminor, minor = true)
px[:set_xticks](1:7:np)
xlabels = fill("Mo", nxticks)
px[:set_xticklabels](xlabels)
px[:set_xlabel]("Wochentag");

Wochenrhythmus

Samstags und sonntags werden erheblich weniger Kinder geboren als unter der Woche. Besonders viele Geburten fallen auf einen Montag oder Freitag. Die fehlenden Geburten von Samstagen und Sonntagen werden also “vorweggenommen” und “nachgeholt”. Die Schwankungen inneralb der Woche liegen bei 70 bis 150 Geburten.

Diskrete Fourrier-Transformation

Wie sieht es mit Schwankungen auf anderen Zeitskalen aus? Um das herauszufinden, wird die Zeitreihe Fourrier-transformiert. Es werden Koeffizienten ermittelt, welche den Beiträgen in unterschiedlichen Frequenzen entsprechen. Das Diagramm des Spektrums zeigt, dass einige Frequenzen, bzw. die entsprechenden Perioden, eine besondere Rolle spielen.

tms[:fft] = fft(tms[:n]);
np = size(tms)[1]
vt = collect(1:np)
Plt.bar(vt[5:80],(abs.(tms[5:80,:fft])), 0.4);

Spektrum

Besonders starke Beiträge liefern die Koeffizienten an den folgenden Positionen:

dfkm1 = Df.DataFrame(Pos = [15, 29, 731, 1462])
dfkm1[:Periode] = round.(nrec ./ (dfkm1[:Pos] .- 1), 1)
dfkm1
PosPeriode
115365.2
229182.6
37317.0
414623.5

Prominent sind also Schwankungen in einem jährlichen, einem halbjährlichen, einem wöchentlichen und einem halbwöchentlichen Rhythmus.

Trend

Blendet man die Schwankungen auf jährlicher oder kürzerer Skala aus, erhält man den langfristigen Trend.

Tm = include("../DStTs.jl")
tms[:trend] = Tm.selectband(Array(tms[:fft]), 1, 10);
xv = tms[:trend]
np = size(xv, 1)
vt = collect(1:np)
px = Plt.axes()
Plt.ylim(125,375)
px[:plot](vt, xv)
px[:set_title]("Geburtenzahlen - Trend")
px[:set_ylabel]("Anzahl")
nxticks = size(1:365:np)[1]
px[:set_xticks](1:365:np)
xlabels = [string(j) for j in 77:91]
px[:set_xticklabels](xlabels)
px[:set_xlabel]("Jahr");

Trend

Geburtenzahlen im Jahresverlauf

Wie sieht der Jahresverlauf aus?

tms[:long] = Tm.selectband(Array(tms[:fft]), 15, 57, 4);
xv = tms[:long]
np = size(xv, 1)
vt = collect(1:np)
px = Plt.axes()
px[:plot](vt, xv)
px[:set_title]("Geburtenzahlen im Jahresverlauf")
px[:set_ylabel]("Anzahl")
nxticks = size(1:365:np)[1]
px[:set_xticks](1:365:np)
xlabels = [string(j) for j in 77:91]
px[:set_xticklabels](xlabels)
px[:set_xlabel]("Jahr");

Jahresverlauf

Die Schwankungen sind etwas kleiner als die Schankungen innerhalb einer Woche. Aber sie sind trotzedem deutlich ausgeprägt. In den Wintermonaten sind die Geburtenzahlen kleiner als im restlichen Jahr.

Betrachtet man den Verlauf nur für vier Jahre wird deutlich sichtbar, dass in der Regel die Geburtenzahl im Verlauf eines Jahres in den Monaten April und Mai einen Höchststand erreicht, dann wieder abfällt um zu einem zweiten Gipfel im Spätsommer anzusteigen bevor das ausgeprägte Tal in den Monaten November bis Januar folgt.

itick = 1
xminorticks = ones(Int, 16)
for iy in [365 * y for y in 0:3], iq in [q * 91 + 1 for q in 0:3]
    xminorticks[itick] = iy + iq
    itick += 1
end
xv = tms[1:1465,:long]
np = size(xv, 1)
vt = collect(1:np)
px = Plt.axes()
px[:plot](vt, xv)
px[:set_title]("Geburtenzahlen im Jahresverlauf")
px[:set_ylabel]("Anzahl")
nxticks = size(1:365:np)[1]
px[:set_xticks](1:365:np)
px[:set_xticks](xminorticks, minor=true)
xlabels = [string(j) for j in 77:91]
px[:set_xticklabels](xlabels)
px[:set_xlabel]("Jahr");

Jahresverlauf - Detail

Die nächste Abbildung zeigt den Trend der Geburtenzahlen überlagert mit den Schwankungen im Jahresverlauf. Die wöchentlichen Schwankungen sind ausgeblendet.

xv = tms[:long] + tms[:trend]
np = size(xv, 1)
vt = collect(1:np)
px = Plt.axes()
px[:plot](vt, xv)
xv = tms[:trend]
px[:plot](vt, xv)
px[:set_title]("Geburtenzahlen im Jahresverlauf mit Trend")
px[:set_ylabel]("Anzahl")
nxticks = size(1:365:np)[1]
px[:set_xticks](1:365:np)
xlabels = [string(j) for j in 77:91]
px[:set_xticklabels](xlabels)
px[:set_xlabel]("Jahr");

Jahresverlauf und Trend

Julia Version: 0.6.2

Startseite