Trinkwasserdaten

Author

rang-cho

Published

December 10, 2024

Einleitung

Trinkwasserdaten im Kanton Zürich, Export aus dem LIMS einer anonymisierten Wasserversorgung mit zwei Probenahmestellen aus den Jahren 2019-2024

Ziele sind:

  • Daten aufbereiten

  • Überschreitungen von 25 mg/l und 40 mg/l Nitrat, E.coli und Enterokokken graphisch darstellen und visuell kenntlich machen (z.B. Plots mit roten Punkten als Überschreitung).

  • Schnittstelle Datenbanken abklären.

  • In ein Shiny App implementieren, um einzelne Gemeinden anzuwählen und darzustellen.

library(tidyverse)
library(here)
library(ggthemes)
library(dplyr)
library(lubridate)

Daten (statisch)

## Daten einlesen als semicolon getrennte Daten. Die ersten 5 Zeilen überspringen
daten_in <- read_delim(here::here("daten/raw/2019-2024_TEST.csv"), skip = 5) |>
  # clean_names hier nutzen, damit auf "saubere" Variablen in Aufbereitung zugegriffen werden kann
  janitor::clean_names() 

## Metadaten extrahieren. Die ersten 2 Zeilen überspringen. Keine Spaltennamen geben.
dictionary_in <- read_delim(here::here("daten/raw/2019-2024_TEST.csv"), skip = 2, col_names = FALSE) |> 
  # clean_names hier nutzen, damit auf "saubere" Variablen in Aufbereitung zugegriffen werden kann
  janitor::clean_names() 

Daten Aufbereitung

Notizen

  • tags sind nicht vereinheitlichet (probiere: test_wv |> count(tags))
  • Unterhalb von detektierbaren Messschwellen wird der Wert “<0.01” zurückgegeben, dadurch wird Spalte zu einer character Spalte. Dieser Werte müssten mit einem numerischen Wert ersetzt werden (e.g. 0) damit Werte grösser 0.01 mg/l korrekt als numerische Werte erkannt werden.
#tags sind nicht relevant für die Auswertung
# Daten säubern
test_wv <- daten_in |> 
  # Spalte ist hat keine Werte. Am Ende wird auf eine Legende hingewiesen 
  select(-koordinaten_lv95) |>  
  slice(-3) |> # Zeile hat keine Werte
  mutate(erhebungsdatum= dmy(erhebungsdatum)) |> 
  # Alle Reihen mit NA für erhebungsdatum sind leer.
  filter(!is.na(erhebungsdatum)) |> 
  # Fügt eine ID Spalte hinzu um Proben zu identifizieren
  mutate(id = seq(1:n())) |> 
  # Bringt die Spalte id an den Anfang des Datensatzes
  relocate(id)
# Das Daten Wörterbuch aus den Metadaten in der Datei erstellen
dictionary <- dictionary_in |> 
  slice(1:4) |> # Nur die ersten 4 Zeilen sind relevant
  # Spalte x1 wurd aus Daten entfernt (i.e. koordinaten_lv95)
  # Spalte id wurde zu Daten hinzugefügt
  # Hier wird Kooridnaten_lv95 zu id umbenannt damit es im Wörterbuch auftaucht
  mutate(x1 = case_when(
    x1 == "Koordinaten LV95" ~ "Eindeutige ID für jede Probe.",
    .default = NA)
    ) |> 
  t() |> # Transponieren, macht aus 4 Reihen 4 Spalten. Rückgabe als Matrix/Array.
  as_tibble() |> # Aus Matrix / Arrax ein tibble machen (Dataframe)
  # Spaltennamen aus test_wv als Variable hinzufügen 
  # names(test_wv) gibt Spaltennamen zurück.
  mutate(variable = names(test_wv)) |> #
  select(variable, # Mit select Reihenfolge bestimmen und Spalten benennen
         einheit = V2, 
         methode = V3, 
         typ = V1, 
         beschreibung = V4) |> 
   # Füllt NA Werte in Spalte typ mit dem Wert darüber (überprüfen!)
  fill(typ, .direction = "down")
{r}
#test_wv |> 
  #glimpse()

#test_wv |> 
  #head()

#test_wv |> 
  #tail()

Daten Visualisierung und Ergebnisse

Table 1 zeigt eine Übersicht zu den Werten von Nitrat, E.coli und Enterokokken.

test_wv |> 
  select(nitrat, escherichia_coli, enterokokken) |> 
  summary(test_wv) |>
  knitr::kable()
Table 1: Parameter Nitrat, E.coli und Enterokokken
nitrat escherichia_coli enterokokken
Min. :12.50 Min. :0 Min. :0
1st Qu.:21.75 1st Qu.:0 1st Qu.:0
Median :24.70 Median :0 Median :0
Mean :23.48 Mean :0 Mean :0
3rd Qu.:26.05 3rd Qu.:0 3rd Qu.:0
Max. :40.70 Max. :0 Max. :0
NA’s :23 NA’s :7 NA’s :7

In Figure 1 und Figure 2 sind mögliche Höchstwertüberschreitungen von Fäkalkeimen dargestellt. Zusätzlich sieht man in Figure 3, ob der Nitrat Höchstwert von 40 mg/l überschritten wurde.

ggplot(data = test_wv,
       mapping = aes(x = erhebungsdatum,
                     y = escherichia_coli)) +
  geom_point() +
  scale_color_manual(values = "blue") +
  geom_vline(xintercept = 1, color = "red", linetype = "dashed", linewidth = 1) +
  facet_wrap(~probenahmestelle) +
  labs(title = "Auswertung Wasserversorgung Test",
         subtitle = "E.coli",
         caption = "KL",
         y = NULL,
         x = NULL) +
    theme_minimal() +
    theme(legend.position = "bottom", panel.grid.major.y = element_blank())
Figure 1: E.coli Höchstwertüberschreitungen
ggplot(data = test_wv,
       mapping = aes(x = erhebungsdatum,
                     y = enterokokken)) +
  geom_point() +
  scale_color_manual(values = "blue") +
  geom_vline(xintercept = 1, color = "red", linetype = "dashed", linewidth = 1) +
  facet_wrap(~probenahmestelle) +
  labs(title = "Auswertung Wasserversorgung Test",
         subtitle = "Enterokokken",
         caption = "KL",
         y = NULL,
         x = NULL) +
    theme_minimal() +
    theme(legend.position = "bottom", panel.grid.major.y = element_blank())
Figure 2: Enterokokken Höchstwertüberschreitungen
ggplot(data = test_wv,
       mapping = aes(x = erhebungsdatum,
                     y = nitrat)) +
  geom_point() +
  scale_color_manual(values = "green") +
  geom_vline(xintercept = 40, color = "red", linetype = "dashed", linewidth = 1) +
  facet_wrap(~probenahmestelle) +
  labs(title = "Auswertung Wasserversorgung Test",
         subtitle = "Nitrat",
         caption = "KL",
         y = NULL,
         x = NULL) +
    theme_minimal() +
    theme(legend.position = "bottom", panel.grid.major.y = element_blank())
Figure 3: Nitrat Höchstwertüberschreitungen

Die Diagramme und Tabelle zeigen, dass es zu keiner Höchstwertüberschreitung an Fäkalkeimen zwischen 2019 und 2024 gekommen ist. Der Höchstwert von 40 mgl/l Nitrat wurde an Teststr. im Jahr 2021 überschritten.

Schlussfolgerungen

  • Es ist möglich mit diesem Vorgehen eine Übersicht über die relevanten Höchstwertüberschreitungen einer Wasserversorgung über einen bestimmten Zeitraum zu gewinnen.

  • Eine gute Datenaufbereitung ist das schwierigste.

Ausblick

  • Schnittstelle Datenbanken abklären, um ein Abruf der Daten aus der Datenbank zu ermöglichen.

  • Datenaufbereitung

  • In ein Shiny App implementieren, um einzelne Gemeinden anzuwählen und darzustellen.