Räumliche und zeitliche Bodenfeuchtedynamik im Einzugsgebiet des Wüstebachs
Übersicht
Das Einzugsgebiet des Wüstebachs liegt in der Eifel und ist ein sogenanntes TERENO-Gebiet. TERENO steht für Terrestrial Environmental Observatories und zeichnet Gebiete aus, in denen ein langfristig angelegtes Umweltmonitoring stattfindet, um Prozesse des globalen Wandels zu untersuchen. Das Monitoring im Wüstebachgebiet umfasst u.a. ein dichtes Messnetz von 150 Sensoren (SoilNet), welche in Tiefen von 5, 20 und 50 cm die Bodenfeuchte erfassen. Auf diese Weise lässt sich sowohl die horizontale wie die vertikale Heterogenität dieser wichtigen Größe untersuchen.
Daten
- Stündliche SoilNet-Messungen des volumetrischen Bodenwassergehalts von 2009 bis 2021 (5, 20 und 50 cm Tiefe) an 150 Messpunkten (auch “Knoten” genannt). Achtung: Die Daten wurden einer Plausibilitätskontrolle unterzogen. Unplausible Daten wurden mit dem Wert -1 multipliziert, so dass unplausible Werte einerseits leicht herausgefiltert werden können, andererseits aber der usprüngliche Messwert rekonstruiert werden kann.
- DEM (Raster)
- Einzugsgebietsgrenzen (Shapefile)
- Wüstebach (Shapefile)
Die Zeitreihendaten stehen auf dem TERENO-Datenportal zur Verfügung, wurden aber zur Nutzung in diesem Kurs bereits heruntergeladen, vorprozessiert und unter Box.UP bereitgestellt (Link, Passwort: umweltdatenverarbeitung).
Ergebnisse
- Ermittle für jeden Monat und jede Messtiefe von 2009 bis 2021 den prozentualen Anteil verfügbarer und plausibler Daten. Stelle dies als Zeitreihendiagramm dar.
- Ermittle für jeden Messknoten und für jede Tiefe den Anteil verfügbarer und plausibler Daten über den gesamten Messzeitraum. Ermittle auch den Mittelwert dieses Anteils über alle drei Messtiefen. Sortiere die Knoten absteigend nach diesem Mittelwert. Wieviele der 150 Knoten haben eine mittlere Verfügbarkeit von über 75 Prozent?
- Stelle nun den monatlichen Mittelwert für die Knoten mit über 75 % Verfügbarkeit als Zeitreihe von 2009 bis 2021 dar (5, 20 und 50 cm Tiefe). Füge darunter einen zusätzlichen Subplot mit dem prozentualen Anteil verfügbarer Daten über die Zeit dar. Erörtere kurz die Bodenfeuchtedynamik in den drei Tiefen, auch unter Berücksichtigung der Datenverfügbarkeit.
- Berechne nun die mittlere Bodenfeuchte für jeden Knoten und jede Tiefe für einen selbst gewählten Zeitraum. Stelle diese berechnete mittlere Bodenfeuchte für alle Knoten als Karte für jede Tiefe dar, in der an der Position jedes Knotens die entsprechende Bodenfeuchte farbkodiert ist. Nutze als Kartenhintergrund die Einzugsgebietsgrenzen und den Verlauf des Wüstebachs, optional auch die Höhenlinien aus dem DEM. Achte darauf, für jede der drei Karten die gleiche Farbskalierung zu nutzen. Erörtere kurz die räumliche Verteilung.
Hinweise
R
-
Die SoilNet-Daten liegen in einer zip-Datei. Anstatt dieses manuell auszupacken, könnt Ihr die Daten auch direkt aus der zip-Datei lesen. Nehmen wir an, in der zip-Datei
the.zip
liegt eine Dateithe.csv
, dann geht das so:read.table(unz("the.zip", "the.csv"), header=TRUE)
-
Die Handhabung der Daten der verschiedenen Tiefen ist einfacher, wenn Ihr diese in einem Dataframe zusammenfasst. Ihr könnt dies durch spaltenweises Zusammenfügen erreichen, praktischer ist aber das zeilenweise aneinanderhängen und dabei eine Spalte für die Messtiefe anzufügen. Dafür müsst Ihr beachten, dass die Spaltennamen in den Dateien der unterschiedlichen Tiefen sind auch unterschiedlich sind. Sie können mit
names(df)
angepasst werden, dann klappt danach auch das aneinanderhängen. -
Ihr könnt gültige Werte (d.h. Werte, die nicht
NA
sind) in einem Vektorx
mit Hilfe vonsum(!is.na(x))
zählen. Mitapply()
lässt sich das dann auch spalten- oder zeilenweise auf Dataframes anwenden. -
Während sich
apply()
eignet, um spalten- oder zeilenweise zu aggregieren, kannaggregate()
dies nur zeilweise, aber dafür lässt sich dabei nach unterschiedlichen Kriterien gruppieren. -
Den Monat einer Datumsangabe kann man wie in Lektion “Mastering Geodata” erklärt extrahieren.
floor_date()
, auch aus dem Paketlubridate
könnte weiterhin nützlich sein, um ein Datum auf einen vollen Monatsbeginn abzurunden. - Die Koordinaten aus einer Tabelle lassen sich in ein Geoobjekt mit
st_as_sf()
(Paketsf
) umwandeln. Wenn diese vorher mit Spalten zu den Bodenfeuchtewerten ergänzt werden (z.B. mitmerge()
), lassen sich mit dem Pakettmap
(siehe Lektion “Mastering Geodata”) Karten erzeugen. Die Farbe der Punkte regelt man in diesem Fall übertm_shape(dasPunkteObjekt") + tm_symbols(col = "SpaltenameBodenfeuchte", breaks = breaks)
Steht statt “SpaltenameBodenfeuchte” ein Vektor mit mehreren Spaltennamen, wird automatisch ein Multipanel-Plot erzeugt. Wenn Ihr
breaks
vorher als Grenzen für die Farblegende definiert, ist diese auch in den verschiedenen Panels konsistent. rasterToContour
aus dem Paketraster
erzeugt Höhenlinien aus einer Rasterkarte - nützlich, wenn man das DEM lieber etwas dezenter darstellen möchte.
Python
- Die SoilNet-Daten liegen in einer zip-Datei. Anstatt dieses manuell auszupacken, könnt Ihr die Daten auch direkt aus der zip-Datei lesen. Dazu gibt es das Paket
zipfile
. Nehmen wir an in der zip-Dateithe.zip
liegt eine Dateithe.csv
, dann:
import zipfile
zipf = zipfile.ZipFile("the.zip", "r")
f = zipf.open("the.csv")
df = pd.read_csv(f, ...)
f.close()
- Ihr könnt gültige Werte (Werte, die nicht
NaN
oderNA
sind) in einemDataFrame
mit Hilfe der Methodecount
zählen.count
lässt sich auch entlang vonaxis
ausführen und mitresample
kombinieren.
# Zählt gültige Werte für jede Spalte
df.count()
# Zählt gültige Werte für jede Zeile
df.count(axis=1)
# Zählt gültige Werte für jede Spalte und jeden Monat (setzt datetime-Index voraus)
df.resample("1M").count()
-
Achtung, die Spaltenbezeichner sind für die Daten aus unterschiedlichen Tiefen auch unterschiedlich. Wenn der DataFrame df5 die Daten aus der Tiefe 5 cm enthält und der DataFrame df20 aus 20 cm Tiefe, könnt Ihr Spaltennamen aus df5 also nicht zur Auswahl von Daten aus df20 verwenden. Wenn für alle drei Tiefen die jeweils gleichen Spalten auswählen wollt, empfiehlt sich daher die Nutzung von
.iloc
. Beispiel:df.iloc[:,[1,3]]
wählt ausdf
alle Zeilen und die 2 und 3 Spalte aus. -
Multiplanel-Plots, also Diagrammme mit mehreren Subplots, erstellt man am einfachsten mit
plt.subplots
. Dieaxes
(subplots), welche dadurch zurückgegeben werden, kann man mitplt.sca()
aktivieren.
fig, ax = plt.subplots(2,1,figsize=(8,5))
ax = ax.ravel()
# Aktiviere erste Zeile:
plt.sca(ax[0])
plt.plot(...)
# Aktiviere zweite Zeile:
plt.sca(ax[1])
plt.plot(...)
- Mit Hilfe der Funktion
plt.scatter
könnt Ihr Punkte entsprechend eines Wertes einfärben. Beispiel: Ihr habt eine DataFrame df mit den Spaltenx
,y
undwert
(x
undy
seien kartesische Koordinaten). Dann färbt Ihr die Punkte wie folgt ein:plt.scatter(df.x, df.y, c=df.wert)
. Mit dem Schlüsselwortcmap
könnt Ihr noch eine Colormap auswählen. Mit den Schlüsselwörternvmin
undvmax
könnt Ihr eine einheitliche Farbskalierung erzwingen - das ist wichtig für die Vergleichbarkeit von Teilabbildungen, die die gleiche Variable ,mit unterschiedlichen Wertebereichen zeigen.