Entwicklung der Luftqualität (Teil 2)

Zeitreihenanalyse der Luftqualität

Im zweiten Teil der Zeitreihenanalyse wird die Entwicklung der Luftqualität in deutschen Großstädten am Beispiel von Bielefeld untersucht. Die zugrunde liegenden Daten stammen von einer Messstation des Landesamts für Natur, Umwelt und Klima Nordrhein-Westfalen (https://www.lanuk.nrw.de/) und enthalten Tagesmittelwerte verschiedener Schadstoffkonzentrationen über einen Zeitraum von 30 Jahren. Analysiert werden die Konzentrationen von Stickstoffmonoxid (NO), Stickstoffdioxid (NO2), Ozon (O3), Feinstaub (PM10) sowie Schwefeldioxid (SO2). Ziel ist es, ein besseres Verständnis für die langfristige Entwicklung der Luftqualität zu gewinnen und möglichen Handlungsbedarf aufzuzeigen.

Autor:in
Zugehörigkeit

Sören Sparmann

Universität Paderborn

Veröffentlichungsdatum

30. Mai 2025

1 Entwicklung der Luftqualität

Wie hat sich die Luftbelastung durch Schadstoffe in den letzten drei Jahrzehnten verändert?

An welchen Tagen treten besonders hohe Konzentrationen auf?

Diesen und weiteren Fragen werden im zweiten Teil der Zeitreihenanalyse untersucht.

Foto „Car exhaust“ (Ausschnitt) von eutrophication&hypoxia (Ruben de Rijcke) unter der Lizenz CC BY 2.0 via Flickr.

Foto „Car exhaust“ (Ausschnitt) von eutrophication&hypoxia (Ruben de Rijcke) unter der Lizenz CC BY 2.0 via Flickr.

2 Daten einlesen

Zunächst werden die Daten erneut mit dem Befehl read_csv() eingelesen und in einem DataFrame df gespeichert.

# Bibliothek für das Arbeiten mit tabellarischen Daten importieren
import pandas as pd

# Daten einlesen
df = pd.read_csv('data/air_quality.csv', index_col='time', parse_dates=True)

# Daten anzeigen
df
NO NO2 O3 PM10 SO2
time
1989-07-01 0.521739 32.739130 32.000000 NaN 0.000000
1989-07-02 1.347826 13.130435 47.291667 NaN 0.000000
1989-07-03 19.545455 26.227273 46.130435 NaN 2.636364
1989-07-04 18.652174 29.826087 43.500000 NaN 6.347826
1989-07-05 20.300000 38.300000 49.619048 NaN 21.352941
... ... ... ... ... ...
2022-12-27 0.000000 11.695652 51.541667 4.541667 NaN
2022-12-28 0.000000 1.869565 58.608696 1.708333 NaN
2022-12-29 0.000000 1.913043 61.043478 0.000000 NaN
2022-12-30 0.000000 3.130435 52.000000 0.000000 NaN
2022-12-31 0.000000 0.000000 55.391304 0.000000 NaN

12237 rows × 5 columns

Hinweis

Der Eintrag NaN (Not a Number) bedeutet, dass an der betreffenden Stelle kein Messwert vorliegt (z.B. weil keine Messung durchgeführt wurde oder ein Messfehler vorliegt).

3 Jahresmittelwerte

Um die Entwicklung der Schadstoffbelastung zu analysieren, werden zunächst die Jahresmittelwerte für den gesamten Zeitraum berechnet.

Da die Daten für die Jahre 1989 und 1990 unvollständig sind, wird der Betrachtungszeitraum auf die Jahre 1991 bis 2024 eingeschränkt, um eine Verfälschung der Mittelwerte zu vermeiden.

import plotly.express as px

# Daten auf den Zeitraum von 1990 bis 2023 einschränken
df = df.loc['1991':'2024']

# Jahresdurchschnitt ermitteln
annual_mean = df.resample('YS').mean()

# Daten visualisieren
fig = px.line(annual_mean, title='Entwicklung der Luftqualität seit 1991')

fig.update_xaxes(title="Jahr")
fig.update_yaxes(title="Schadstoffkonzentration<br>Jahresmittelwert")
fig.update_legends(title="Schadstoff")

fig.show()

Aufgabe 4

  1. Wie hat sich die Schadstoffbelastung in den letzten drei Jahrzehnten entwickelt?
  2. Wie hat sich die COVID-19-Pandemie (2020 - 2023) auf die Luftqualität ausgewirkt?
  3. Wie lässt sich die Entwicklung der einzelnen Schadstoffe erklären? Recherchiere im Internet nach Ursachen für den Rückgang bzw. Zuwachs des jeweiligen Schadstoffs! (1-2 Stichpunkte)

(10 Minuten)

    • Die Schadstoffkonzentration hat mit Außnahme von Ozon insgesamt kontinuierlich abgenommen.
    • Die Schwefeldioxidkonzentration ist so niedrig, dass diese nicht mehr gemessen wird.
  1. Die Schadstoffkonzentration hat während der Anfangsphase der Covid-19-Pandemie stark abgenommen und hat anschließend wieder zugenommen.

  2. Der folgende Ausschnitt aus einem Artikel liefert eine Erklärung für den Anstieg der Ozonkonzentration:

    Bodennahes Ozon wird nicht direkt freigesetzt, sondern bei intensiver Sonneneinstrahlung durch komplexe photochemische Prozesse aus Vorläuferstoffen - überwiegend Stickstoffoxiden und flüchtigen organischen Verbindungen - gebildet. Es wird deshalb als sekundärer Schadstoff bezeichnet. Hohe Lufttemperaturen und starke Sonneneinstrahlung begünstigen die Entstehung von bodennahem Ozon in der ⁠Atmosphäre⁠. Dies ist typisch für die meteorologischen Bedingungen während sommerlicher Hochdruckwetterlagen.

    Quelle: Umweltbundesamt

4 Durchschnittlicher Jahresverlauf

In welchem Monaten ist die Schadstoffbelastung in der Luft besonders hoch?

Um die Daten anhand der Monate zu gruppieren, muss zunächst der Monat für jeden Eintrag ermittelt werden. Dazu wird auf das Attribut month (Monat) zugegriffen.

# Monat ermitteln (1 = Januar, 12 = Dezember)
month = df.index.month
month
Index([ 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
       ...
       12, 12, 12, 12, 12, 12, 12, 12, 12, 12],
      dtype='int32', name='time', length=11688)
Hinweis

Anders als zuvor wurden hier die Monate aus verschiedenen Jahren gruppiert, um einen mittleren Jahresverlauf zu ermitteln.

Anschließend werden die Daten anhand der Liste der Monate gruppiert und der Mittelwert berechnet.

# Daten nach Monat gruppieren und mitteln
monthly_mean = df.groupby(month).mean()
monthly_mean
NO NO2 O3 PM10 SO2
time
1 18.280821 28.412609 25.038202 22.280190 7.457311
2 18.339985 30.732329 30.847334 24.644027 8.744151
3 14.958832 28.390212 40.894867 26.058779 4.870784
4 11.833303 26.491224 52.328747 23.706554 3.482693
5 7.787951 22.956371 56.593024 16.691358 2.836581
6 5.799762 20.174957 57.299202 16.436150 1.902984
7 4.874666 19.144231 55.585062 15.762190 2.276104
8 6.606915 22.517154 50.344610 16.297087 1.773324
9 14.304542 26.118003 33.441744 17.687468 2.074508
10 20.932175 26.534105 23.241723 18.308706 3.352484
11 23.768413 28.474296 18.678254 19.110537 4.437543
12 21.100979 27.280972 21.664213 19.391751 5.482655
# Monatsnamen verwenden (statt Zahlen)
monthly_mean.index = ['Januar', 'Feburar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember']
monthly_mean
NO NO2 O3 PM10 SO2
Januar 18.280821 28.412609 25.038202 22.280190 7.457311
Feburar 18.339985 30.732329 30.847334 24.644027 8.744151
März 14.958832 28.390212 40.894867 26.058779 4.870784
April 11.833303 26.491224 52.328747 23.706554 3.482693
Mai 7.787951 22.956371 56.593024 16.691358 2.836581
Juni 5.799762 20.174957 57.299202 16.436150 1.902984
Juli 4.874666 19.144231 55.585062 15.762190 2.276104
August 6.606915 22.517154 50.344610 16.297087 1.773324
September 14.304542 26.118003 33.441744 17.687468 2.074508
Oktober 20.932175 26.534105 23.241723 18.308706 3.352484
November 23.768413 28.474296 18.678254 19.110537 4.437543
Dezember 21.100979 27.280972 21.664213 19.391751 5.482655
# Jahresverlauf
fig = px.line(monthly_mean, title="Durchschnittliche Schadstoffkonzentration in Verlauf eines Jahres")

fig.update_xaxes(title="Monat")
fig.update_yaxes(title="Schadstoffkonzentration<br>Monatsmittelwert [µg/m<sup>3</sup>]")
fig.update_legends(title="Schadstoff")

fig.show()

Aufgabe 5

  1. Welche Schadstoffe sind eher im Winter / eher im Sommer vorhanden?
  2. Wie lassen sich die unterschiedlichen Verläufe erklären? Nenne mögliche Ursachen! (Stichpunkte)

(10 Minuten)

  • Die Kontentration von NO, NO2, PM10 und SO2 sind im Winter höher als im Sommer, da in dieser Jahrezeit mehr geheizt wird.
  • Die Ozonkonzentration ist dagegen im Sommer erhöht, da die hohen Temperaturen die Bildung von bodennahem Ozon begünstigen.

5 Durchschnittliche Schaddstoffbelastung nach Wochentag

Auf die gleiche Weise wie zuvor lassen sich die Daten auch anhand des Wochentags gruppieren. Hierfür wird das Attribut dayofweek (Wochentag) verwendet.

# Wochentag Monday=0, Sunday=6
dayofweek = df.index.dayofweek
dayofweek
Index([1, 2, 3, 4, 5, 6, 0, 1, 2, 3,
       ...
       3, 4, 5, 6, 0, 1, 2, 3, 4, 5],
      dtype='int32', name='time', length=11688)
# Daten nach Wochentag gruppieren
grouped = df.groupby(dayofweek)

# Mittelwert berechnen
weekday_mean = grouped.mean()

# Wochentagsnamen verwenden
weekday_mean.index = ['Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag', 'Sonntag']

fig = px.bar(weekday_mean, barmode='group', title="Durchschnittliche Schadstoffkonzentration nach Wochentag")

fig.update_xaxes(title='Wochentag')
fig.update_yaxes(title='Schadstoffkonzentration')
fig.update_legends(title='Schadstoff')

fig.show()

5.1 Ozon Weekend Effect

Der Ozone Weekend Effect in Städten bezeichnet das Phänomen, dass die Ozonkonzentrationen an Wochenenden oft höher sind als an Werktagen, trotz geringerer Emissionen von Vorläuferstoffen wie Stickoxiden. Dies liegt daran, dass an Werktagen Stickoxide aus Verkehr und Industrie als Ozonzerstörer wirken, während an Wochenenden die geringeren Emissionen dazu führen, dass weniger Ozon abgebaut wird. Zudem tragen veränderte meteorologische Bedingungen und eine Verschiebung der chemischen Prozesse zur Ozonbildung an Wochenenden bei. Die genaue Dynamik variiert je nach Stadt und regionalen Bedingungen.

Quelle: Pierre Sicard, Elena Paoletti, Evgenios Agathokleous, Valda Araminienė, Chiara Proietti, Fatimatou Coulibaly, Alessandra De Marco, Ozone weekend effect in cities: Deep insights for urban air pollution control, Environmental Research, Volume 191, 2020

6 Feinstaub an Silvester und Neujahr

Vielleicht hast du schon einmal davon gehört, dass die Feinstaubbelastung in der Silvesternacht besonders hoch sein soll. Aber stimmt das wirklich?

In den letzten beiden Abschnitt wurden die Daten mit der groupby() Methode nach dem Attributen df.index.month (Monat) und df.index.dayofweek (Wochentag) gruppiert.

Aufgabe 6

  • Gruppiere die Daten nach dem Tag im Jahr. Verwende dafür das Attribut df.index.dayofyear.
  • Überprüfe, ob die Feinstaubbelastung an Silvester und Neujahr höher ist als im Rest des Jahres!

(15 Minuten)

fig = px.line(df.groupby(df.index.dayofyear).mean())

fig.update_xaxes(title='Tag')
fig.update_yaxes(title='Schadstoffkonzentration')
fig.update_legends(title='Schadstoff')

fig.show()

In der Abbildung ist ein deutlicher Anstieg der Feinstaubbelastung and Silvester und Neujahr zu beobachten.

7 Zusammenfassung

In diesem Notebook hast du gelernt, wie du:

  • Daten mit der Funktion read_csv() einlesen kannst,
  • ein Liniendiagramm mit line() und ein Säulendiagramm mit bar() erstellst,
  • eine bestimmte Spalte aus den Daten selektierst, z. B. mit df[<Spalte>],
  • Daten anhand einer Bedingung filterst, z. B. mit df[cond],
  • Zeitreihen mit resample() in Zeitintervalle gruppierst und mit Funktionen wie count(), mean(), min() oder max() aggregierst.

Wiederverwendung

Zitat

Mit BibTeX zitieren:
@online{sparmann2025,
  author = {Sparmann, Sören},
  title = {Entwicklung der Luftqualität (Teil 2)},
  date = {2025-05-30},
  url = {https://climate-data-entrepreneurial-club.netlify.app/modul_2/submodules/01_luftqualitaet/02_entwicklung_luftqualitaet.html},
  langid = {de}
}
Bitte zitieren Sie diese Arbeit als:
Sparmann, Sören. 2025. “Entwicklung der Luftqualität (Teil 2).” May 30, 2025. https://climate-data-entrepreneurial-club.netlify.app/modul_2/submodules/01_luftqualitaet/02_entwicklung_luftqualitaet.html.
close all nutshells