Kantonale Bodenüberwachung

Überwachungsperioden 1-5 (1995-2019)

Einleitung

Die Kantonale Bodenüberwachung (KaBo) ist ein langfristiges Monitoringprogramm der Fachstelle Bodenschutz (FaBo). Seit 1995 beproben und analysieren wir die Böden regelmässig an über 500 Standorten im Kanton Zürich. Ziel ist es, den Zustand und die Entwicklung verschiedener chemischer und physikalischer Eigenschaften des Bodens abzubilden. Die KaBo fokussiert nicht auf einzelne Standorte, sondern vermittelt ein Gesamtbild über den Kanton.

Daten

Beschreibung

Der Datensatz enthält Messdaten

  • zu rund 500 Standorten mit den Nutzungsarten Acker, Grünland und Wald.

  • von 5 Zeitpunkten (von Messperiode 6 ist die Beprobung abgeschlossen, die Analysen liegen noch nicht vollständig vor)

  • für die Schwermetalle Cadmium, Chrom, Kupfer, Quecksilber sowie

  • den Gehalt an organischer Substanz und den pH-Wert

Weitere Messparameter sind in den Daten enthalten, wurden aber bisher nicht ausgewertet.

Nicht alle Parameter liegen an allen Standorten und Tiefen lückenlos vor. Sind Schwermetallgehalte so niedrig, dass sie unterhalb der technischen Bestimmungsgrenze liegen, wird ein Platzhalterwert angegeben.

Datenquelle: Die Daten zu einzelnen Standorten lassen sich im GIS-Browser im Layer “Kantonale Bodenüberwachung” abfragen. Die Übersicht zu allen Standorten wurde von der Fachstelle Bodenschutz lokal erzeugt und ist zurzeit nicht frei verfügbar.

Analyseziele

  • Zustand: Für die Schwermetalle wird dargestellt und beschrieben, wie die Werteverteilung (Mittelwert und üblicher Bereich = mittlere 80 % der Werte) zum aktuellsten Messzeitpunkt aussieht.

  • Entwicklung: Für die Parameter organische Substanz sowie pH-Wert wird dargestellt, wie sich der mittlere Wert seit Beginn der Überwachung entwickelt hat

Aufbereitung

Code
# #| code-fold: show
#| code-overflow: wrap
# Rohdaten aufbereiten:
  # 1.Tabelle mit Standortinformationen
  # unnötige Spalten entfernen
gemeinden <- select(gemeinden_roh,StandortID,PolitGemeinde,x_200,y_200) |> 
  # Formatierung Gemeindenamen
  mutate(Gemeinde = str_to_title(PolitGemeinde), .keep = "unused"
  ) |> 
  mutate(Gemeinde = str_remove_all(Gemeinde, fixed(" (Zh)"))) |> 
  mutate(Gemeinde = str_replace(Gemeinde, " Am Albis", " a.A.")) |> 
  mutate(Gemeinde = str_replace(Gemeinde, " Am See", " a.S.")) |> 
  mutate(Gemeinde = str_replace(Gemeinde, " Am Irchel", " a.I.")) |>
  mutate(Gemeinde = str_replace(Gemeinde, " An Der Thur", " a.d.T")) |> 
  mutate(Gemeinde = str_replace(Gemeinde, "ae", "ä")) |> 
  mutate(Gemeinde = str_replace(Gemeinde, "oe", "ö")) |> 
  mutate(Gemeinde = str_replace(Gemeinde, "ue", "ü")) |> 
  mutate(Gemeinde = str_remove(Gemeinde, " Zh"))
  # formatierte Daten als csv ablegen
write_csv(gemeinden,here::here("daten/processed/gemeinden_formatiert.csv"))
 # 2.Tabelle mit Messdaten
 # unnötige Spalten entfernen
kabodaten <- select(kabodaten_roh,
                    StandortID,
                    p.dat,
                    periode,
                    KaboStatus,
                    AktStandorttyp,
                    Parameter,
                    WertOB = Wert_plot_OB,
                    WertOB_tab = Wert_tab_OB,
                    Klasse_OB,
                    WertUB = Wert_plot_UB,
                    WertUB_tab = Wert_tab_UB,
                    Klasse_UB) |> mutate( 
                # Datumswert von String in Datum umwandeln
                      p.dat = dmy(p.dat)
                    ) |> mutate(
                # Spaltennamen und Textwerte vereinfachen
                      AktStandorttyp = case_when(
                        startsWith(AktStandorttyp,"Acker") ~ "Acker",
                        AktStandorttyp == "" ~ "Wald",
                        .default = AktStandorttyp)
                    ) |> mutate(
                        param_txt = case_when(
                          Parameter == "HGT_PPM" ~ "Quecksilber",
                          Parameter == "CDT_PPM" ~ "Cadmium",
                          Parameter == "CUT_PPM" ~ "Kupfer",
                          Parameter == "PBT_PPM" ~ "Blei",
                          Parameter == "ZNT_PPM" ~ "Zink",
                          Parameter == "CRT_PPM" ~ "Chrom",
                          Parameter == "NIT_PPM" ~ "Nickel",
                          Parameter == "ORG_SUB" ~ "Organische Substanz",
                          Parameter == "PHCA" ~ "pH",
                          Parameter == "LAGDICHT_BURG" ~ "Lagerungsdichte",
                          .default = NA)
                    ) |> mutate(
                # neue Spalte mit Masseinheit
                        einheit = case_when(
                          endsWith(Parameter,"PPM") ~ "ppm",
                          Parameter == "ORG_SUB" ~ "%",
                          Parameter == "PHCA" ~ " ",
                          Parameter == "LAGDICHT_BURG" ~ "kg/l",
                          .default = NA)
                    )
 # formatierte Tabelle als csv ablegen
write_csv(kabodaten,here::here("daten/processed/kabodaten_formatiert.csv"))
# 3. zusammenführen der beiden Tabellen
 # Darstellung aufräumen
kabo <- left_join(kabodaten,gemeinden,by="StandortID") |> 
  select(StandortID,KaboStatus,AktStandorttyp,x_200,y_200,Gemeinde,periode,p.dat,param_txt,einheit,WertOB,WertOB_tab,Klasse_OB,WertUB,WertUB_tab,Klasse_UB)
 # komplette, formatierte Tabelle als csv ablegen
write_csv(kabo,here::here("daten/processed/daten_komplett.csv"))

Die für die Bodendatenbank der Fachstelle formatierten Rohdaten wurden in ein einfach lesbares, einheitliches Format vereinfacht und unnötige Spalten entfernt. Die aufbereiteten Daten können nun hier als Textfile betrachtet werden.

Ergebnisse

Zustand Schwermetalle

Im folgenden sind die Messwerte für den Oberboden der Schwermetalle Cadmium (Abb. 1), Chrom (Abb. 2), Kupfer (Abb. 3) und Quecksilber (Abb. 4) aus der letzten vollständig vorliegenden Überwachungsperiode (2015-2019) abgebildet und der auf den KaBo-Standorten gefundene übliche Wertebereich tabellarisch zusammengefasst (Tab. 1 für Cadmium, Tab. 2 für Chrom, Tab. 3 für Kupfer und Tab. 4 für Quecksilber.

Die gelbe Linie “RW” steht für die Höhe des Richtwerts nach Verordnung über Belastungen des Bodens (VBBo). Vereinzelt liegen Extremwerte ausserhalb des abgebildeten Bereichs vor.

Code
filter(kabo,param_txt=="Cadmium",periode == 5) |>
  ggplot(aes(x = AktStandorttyp,
           y = WertOB,
           fill = AktStandorttyp))+
  geom_hline(yintercept = 0.8, color = "gold", linewidth = 1) +
  geom_text(label = "RW", x= Inf, hjust= 1, y=0.775,color = "gold", size = 16/.pt) +
  geom_boxplot(show.legend = F) +
  scale_fill_manual(values=farben)+
  theme_gray(base_size = 22) +
  theme(panel.background = element_blank(),
        panel.grid.major.y = element_line(color = "grey85"),
        panel.grid.major.x = element_line(color = NA),
        axis.ticks = element_blank())+
  scale_x_discrete(name = NULL) +
  scale_y_continuous(name = "Gehalt [ppm]",limits = c(0,.8),breaks = seq(0,.8,.1)) +
  labs(title = "Cadmium")
filter(kabo,param_txt=="Cadmium",periode == 5) |> 
  group_by(AktStandorttyp) |> 
  summarise(n = n(),
            untquant = round(quantile(WertOB,.1),2),
            Median = round(median(WertOB),2),
            obquant = round(quantile(WertOB,.9),2)) |> 
  knitr::kable(col.names = c("", "Anz.", "tief", "Median", "hoch")) |> 
  column_spec(4, bold=T)
filter(kabo,param_txt=="Chrom",periode == 5) |>
  ggplot(aes(x = AktStandorttyp,
           y = WertOB,
           fill = AktStandorttyp)) +
  geom_hline(yintercept = 50, color = "gold", linewidth = 1) +
  geom_text(label = "RW", x= Inf, hjust= 1, y=47.5,color = "gold", size = 16/.pt) +
  geom_boxplot(show.legend = F) +
  scale_fill_manual(values=farben) +
  theme_gray(base_size = 22) +
  theme(panel.background = element_blank(),
        panel.grid.major.y = element_line(color = "grey85"),
        panel.grid.major.x = element_line(color = NA),
        axis.ticks = element_blank())+
  scale_x_discrete(name = NULL) +
  scale_y_continuous(name = "Gehalt [ppm]",limits = c(0,70),breaks = seq(0,70,10)) +
  labs(title = "Chrom")
filter(kabo,param_txt=="Chrom",periode == 5) |> 
  group_by(AktStandorttyp) |> 
  summarise(n = n(),
            untquant = round(quantile(WertOB,.1),1),
            Median = round(median(WertOB),1),
            obquant = round(quantile(WertOB,.9),1)) |> 
  knitr::kable(col.names = c("", "Anz.", "tief", "Median", "hoch")) |> 
  column_spec(4, bold=T)
filter(kabo,param_txt=="Kupfer",periode == 5) |>
  ggplot(aes(x = AktStandorttyp,
           y = WertOB,
           fill = AktStandorttyp))+
  geom_hline(yintercept = 40, color = "gold", linewidth = 1) +
  geom_text(label = "RW", x= Inf, hjust= 1, y=37.5,color = "gold", size = 16/.pt) +
  geom_boxplot(show.legend = F) +
  scale_fill_manual(values=farben) +
  theme_gray(base_size = 22) +
  theme(panel.background = element_blank(),
        panel.grid.major.y = element_line(color = "grey85"),
        panel.grid.major.x = element_line(color = NA),
        axis.ticks = element_blank())+
  scale_x_discrete(name = NULL) +
  scale_y_continuous(name = "Gehalt [ppm]",limits = c(0,50),breaks = seq(0,50,10)) +
  labs(title = "Kupfer")
filter(kabo,param_txt=="Kupfer",periode == 5) |> 
  group_by(AktStandorttyp) |> 
  summarise(n = n(),
            untquant = round(quantile(WertOB,.1),1),
            Median = round(median(WertOB),1),
            obquant = round(quantile(WertOB,.9),1)) |> 
  knitr::kable(col.names = c("", "Anz.", "tief", "Median", "hoch")) |> 
  column_spec(4, bold=T)
filter(kabo,param_txt=="Quecksilber",periode == 5) |>
  ggplot(aes(x = AktStandorttyp,
           y = WertOB,
           fill = AktStandorttyp))+
  geom_text(label = "RW = 0.5 ppm", x= -Inf, hjust= 0, y=.27,color = "gold", size = 18/.pt) +
  geom_boxplot(show.legend = F) +
  scale_fill_manual(values=farben) +
  theme_gray(base_size = 22) +
  theme(panel.background = element_blank(),
        panel.grid.major.y = element_line(color = "grey85"),
        panel.grid.major.x = element_line(color = NA),
        axis.ticks = element_blank())+
  scale_x_discrete(name = NULL) +
  scale_y_continuous(name = "Gehalt [ppm]",limits = c(0,.27),breaks = seq(0,.250,.050)) +
  labs(title = "Quecksilber")
filter(kabo,param_txt=="Quecksilber",periode == 5) |> 
  group_by(AktStandorttyp) |> 
  summarise(n = n(),
            untquant = round(quantile(WertOB,.1),2),
            Median = round(median(WertOB),2),
            obquant = round(quantile(WertOB,.9),2)) |> 
  knitr::kable(col.names = c("", "Anz.", "tief", "Median", "hoch")) |> 
  column_spec(4, bold=T)
Abb. 1: Verteilung der Cadmium-Gehalte in Oberböden unterschiedlicher Nutzung
Tab. 1: Üblicher Wertebereich für Cadmiumgehalte in Oberböden [ppm]. tief und hoch bezeichnen das 10. und 90. Quantil der Werte
Anz. tief Median hoch
Acker 226 0.17 0.27 0.38
Grünland 103 0.21 0.32 0.50
Wald 179 0.08 0.15 0.31
Abb. 2: Verteilung der Chrom-Gehalte in Oberböden unterschiedlicher Nutzung
Tab. 2: Üblicher Wertebereich für Chromgehalte in Oberböden [ppm]. tief und hoch bezeichnen das 10. und 90. Quantil der Werte
Anz. tief Median hoch
Acker 226 18.4 26.6 39.2
Grünland 103 22.3 30.6 43.4
Wald 179 0.0 22.9 30.0
Abb. 3: Verteilung der Kupfer-Gehalte in Oberböden unterschiedlicher Nutzung
Tab. 3: Üblicher Wertebereich für Kupfergehalte in Oberböden [ppm]. tief und hoch bezeichnen das 10. und 90. Quantil der Werte
Anz. tief Median hoch
Acker 226 14.3 19.7 30.1
Grünland 103 12.2 17.8 25.7
Wald 179 5.6 8.9 14.1
Abb. 4: Verteilung der Quecksilber-Gehalte in Oberböden unterschiedlicher Nutzung
Tab. 4: Üblicher Wertebereich für Quecksilbergehalte in Oberböden [ppm]. tief und hoch bezeichnen das 10. und 90. Quantil der Werte
Anz. tief Median hoch
Acker 226 0.03 0.05 0.08
Grünland 103 0.05 0.07 0.12
Wald 179 0.00 0.00 0.00

Für viele Schwermetalle zeigt sich, dass die Belastungen mit zunehmender Bearbeitung der Böden tendenziell zunehmen. So sind Waldböden in der Regel mit Abstand am wenigsten belastet. Generell sind nur vereinzelt Böden so stark belastet, dass sie Beurteilungswerte überschreiten.

Diese Auswertung deckt nur eine Auswahl von Schwermetallen ab, deren Eintrags- und Austragswege unterschiedlich sind.

Entwicklung Kennwerte

Ein wichtiges Ziel der Dauerüberwachung ist das Erkennen von möglichen Veränderungen im Boden. Anhand der Kennwerte organische Substanz (“Humusgehalt”, Abb. 5) und pH-Wert (Abb. 6) wird der Verlauf der Messwerte seit Aufnahme der Dauerüberwachung dargestellt. Da Prozesse in Böden oft stetig und langsam ablaufen, sind Veränderungen oft erst nach langer Zeit sicher festzustellen. Umso wichtiger ist ein langfristiges und standardisiertes Messnetz.

Organische Substanz (Humusgehalt)

Code
summ_orgsub <- filter(kabo,param_txt=="Organische Substanz", !is.na(WertOB)) |>
  group_by(periode, AktStandorttyp) |> 
  summarise(Med = median(WertOB),
            Unten = quantile(WertOB,.1),
            Oben = quantile(WertOB, .9),
            anz = n())
summ_orgsub |>
  filter(AktStandorttyp=="Acker") |> 
  ggplot(aes(x = periode,
         y = Med)) +
  geom_ribbon(aes(ymin = Unten, ymax = Oben), fill = farben[1], alpha = .4, show.legend = F) +
  geom_line(color = farben[1], linewidth = 1.5) +
  theme_gray(base_size = 22) +
  theme(panel.background = element_blank(),
        panel.grid.major.y = element_line(color = "grey90"),
        panel.grid.major.x = element_line(color = NA),
        axis.ticks = element_blank(),
        axis.text.x = element_text(angle = 45, hjust = 1, vjust = 1.2)) +
  scale_y_continuous(name = "Gehalt [%]",limits = c(2,7.5),breaks = seq(2,7.5,.5)) +
  scale_x_discrete(name = "Messperiode", limits = factor(1:6),breaks = factor(1:6), labels=messperioden)
  

summ_orgsub |>
  filter(AktStandorttyp=="Grünland") |> 
  ggplot(aes(x = periode,
         y = Med)) +
  geom_ribbon(aes(ymin = Unten, ymax = Oben), fill = farben[2], alpha = .4, show.legend = F) +
  geom_line(color = farben[2], linewidth = 1.5) +
  theme_gray(base_size = 22) +
  theme(panel.background = element_blank(),
        panel.grid.major.y = element_line(color = "grey90"),
        panel.grid.major.x = element_line(color = NA),
        axis.ticks = element_blank(),
        axis.text.x = element_text(angle = 45, hjust = 1, vjust = 1.2)) +
  scale_y_continuous(name = "Gehalt [%]",limits = c(3.5,9.5),breaks = seq(3.5,9.5,.5)) +
  scale_x_discrete(name = "Messperiode", limits = factor(1:6),breaks = factor(1:6), labels=messperioden)
  

summ_orgsub |>
  filter(AktStandorttyp=="Wald") |> 
  ggplot(aes(x = periode,
         y = Med)) +
  geom_ribbon(aes(ymin = Unten, ymax = Oben), fill = farben[3], alpha = .4, show.legend = F) +
  geom_line(color = farben[3], linewidth = 1.5) +
  theme_gray(base_size = 22) +
  theme(panel.background = element_blank(),
        panel.grid.major.y = element_line(color = "grey90"),
        panel.grid.major.x = element_line(color = NA),
        axis.ticks = element_blank(),
        axis.text.x = element_text(angle = 45, hjust = 1, vjust = 1.2)) +
  scale_y_continuous(name = "Gehalt [%]",limits = c(3,10),breaks = seq(3,10,1)) +
  scale_x_discrete(name = "Messperiode", limits = factor(1:6),breaks = factor(1:6), labels=messperioden)
(a) Acker
(b) Grünland
(c) Wald
Abb. 5: Entwicklung der Humusgehalte in Oberböden unterschiedlicher Nutzung

Über alle Nutzungsarten hinweg sind die Humusgehalt seit Überwachungsbeginn tendenziell leicht zunehmend, am stärksten auf Grünlandstandorten.

pH-Wert

Code
summ_ph <- filter(kabo,param_txt=="pH", !is.na(WertOB)) |>
  group_by(periode, AktStandorttyp) |> 
  summarise(Med = median(WertOB),
            Unten = quantile(WertOB,.1),
            Oben = quantile(WertOB, .9),
            anz = n())
summ_ph |>
  filter(AktStandorttyp=="Acker") |> 
  ggplot(aes(x = periode,
         y = Med)) +
  geom_ribbon(aes(ymin = Unten, ymax = Oben), fill = farben[1], alpha = .4, show.legend = F) +
  geom_line(color = farben[1], linewidth = 1.5) +
  theme_gray(base_size = 22) +
  theme(panel.background = element_blank(),
        panel.grid.major.y = element_line(color = "grey90"),
        panel.grid.major.x = element_line(color = NA),
        axis.ticks = element_blank(),
        axis.text.x = element_text(angle = 45, hjust = 1, vjust = 1.2)) +
  scale_y_continuous(name = "pH-Wert",limits = c(5,7.5),breaks = seq(5,7.5,.5)) +
  scale_x_discrete(name = "Messperiode", limits = factor(1:6),breaks = factor(1:6), labels=messperioden)
  

summ_ph |>
  filter(AktStandorttyp=="Grünland") |> 
  ggplot(aes(x = periode,
         y = Med)) +
  geom_ribbon(aes(ymin = Unten, ymax = Oben), fill = farben[2], alpha = .4, show.legend = F) +
  geom_line(color = farben[2], linewidth = 1.5) +
  theme_gray(base_size = 22) +
  theme(panel.background = element_blank(),
        panel.grid.major.y = element_line(color = "grey90"),
        panel.grid.major.x = element_line(color = NA),
        axis.ticks = element_blank(),
        axis.text.x = element_text(angle = 45, hjust = 1, vjust = 1.2)) +
  scale_y_continuous(name = "pH-Wert",limits = c(4.5,7),breaks = seq(4.5,7,.5)) +
  scale_x_discrete(name = "Messperiode", limits = factor(1:6),breaks = factor(1:6), labels=messperioden)
  

summ_ph |>
  filter(AktStandorttyp=="Wald") |> 
  ggplot(aes(x = periode,
         y = Med)) +
  geom_ribbon(aes(ymin = Unten, ymax = Oben), fill = farben[3], alpha = .4, show.legend = F) +
  geom_line(color = farben[3], linewidth = 1.5) +
  theme_gray(base_size = 22) +
  theme(panel.background = element_blank(),
        panel.grid.major.y = element_line(color = "grey90"),
        panel.grid.major.x = element_line(color = NA),
        axis.ticks = element_blank(),
        axis.text.x = element_text(angle = 45, hjust = 1, vjust = 1.2)) +
  scale_y_continuous(name = "pH-Wert",limits = c(3.5,6),breaks = seq(3.5,6,.5)) +
  scale_x_discrete(name = "Messperiode", limits = factor(1:6),breaks = factor(1:6), labels=messperioden)
(a) Acker
(b) Grünland
(c) Wald
Abb. 6: Entwicklung des pH-Werts in Oberböden unterschiedlicher Nutzung

Beim pH-Wert sind keine klaren Entwicklungen zu sehen. Die Mittelwerte bewegen sich in der Spannbreite von einer halben pH-Einheit.

Schlussfolgerungen

  • Der Datensatz der Kantonalen Bodenüberwachung umfasst eine Vielzahl von Parametern

  • Diese wurden hier nur exemplarisch beschrieben.

  • Die Unterteilung nach Standortnutzung ist sinnvoll, zeigen sich doch teils deutliche Unterschiede sowohl in der absoluten Wertverteilung, als teilweise auch in der Entwicklung über die Zeit.

  • Durch die oft langsamen Prozesse im Boden sind auch Veränderungen erst nach längerer Zeit sicher erkennnbar.

  • Neben der Nutzungsart können die Daten anhand weiterer Standorteigenschaften gruppiert und ausgewertet werden. Somit lassen sich weitere Faktoren finden, welche auf die Qualität unserer Böden Einfluss haben.