5.5. Einen Zeitverlauf einfügen#
Story
Nachdem Amir Weber die Bezirke und Bewässerungsmengen verglichen hat, interessiert ihn nun, welche Rolle das Alter der Bäume spielt. Er fragt sich, ob bestimmte Jahrgänge besonders häufig gegossen werden, wie etwa jüngere Bäume, die nach wissenschaftlicher Empfehlung mehr Wasser benötigen, oder ältere Bäume, die empfindlicher auf Trockenstress reagieren. Um dieser Frage nachzugehen, betrachten Sie die gesamte gegossene Wassermenge pro Pflanzjahr und erhalten so einen Überblick darüber, welche Baumkohorten am stärksten vom Engagement der Bürger:innen profitieren.
Zweck dieser Übung
Diese Übung zeigt:
wie Bewässerungsdaten nach Pflanzjahren aggregiert werden können;
welche Baumjahrgänge besonders viel oder wenig Wasser erhalten;
und wie zeitliche oder altersbezogene Faktoren Hinweise auf Pflegebedarf und Gießverhalten liefern.
Nachdem Sie die räumlichen Unterschiede der Bewässerung betrachtet haben, richten Sie Ihren Fokus nun auf zeitliche und altersbezogene Faktoren des Engagements. Denn das Bürgerengagement beim Gießen wird eventuell nicht nur durch den Bezirk geprägt, sondern vielleicht auch durch:
zeitliche Muster (z. B. verändert sich die Bewässerungsaktivität über die Jahre?),
Baumalter bzw. Pflanzjahr (wissenschaftlich ist belegt, dass besonders junge und teilweise auch sehr alte Bäume ein erhöhtes Wasservolumen benötigen),
Um diese Aspekte besser zu verstehen, untersuchen Sie zwei zentrale Fragen:
1. Wie hat sich die Bewässerungsmenge über die Jahre entwickelt? → Gibt es Trends, Spitzenjahre oder Rückgänge?
2. Werden bestimmte Baumjahrgänge (Pflanzjahre) häufiger gegossen als andere? → Deutet das auf besondere Pflegebedarfe oder engagiertes Handeln hin?
Die folgenden Visualisierungen zeigen deshalb sowohl Trends im Jahresverlauf als auch die insgesamt gegossene Wassermenge pro Pflanzjahr, um das Zusammenspiel zwischen Baumalter, Bedarf und Engagement sichtbar zu machen. Eine chronologische Trenddarstellung ermöglicht es, zeitliche Entwicklungen und Muster im Gießverhalten zu erkennen. Nutzer:innen können nachvollziehen, wie sich die Bewässerungsaktivität über die Jahre hinweg verändert. Solche Erkenntnisse helfen nicht nur bei der Einschätzung des aktuellen Bedarfs, sondern auch bei der Planung zukünftiger Gießaktionen. Darüber hinaus macht die Visualisierung Schwankungen sichtbar. Für die Community kann die Trendlinie zudem motivierend wirken: Ein Aufwärtstrend zeigt wachsendes Engagement, während ein Abfall zum Handeln aufrufen kann. Langfristig liefert die chronologische Darstellung wertvolle Daten für die Evaluation von Maßnahmen und hilft zu verstehen, wann und warum Menschen aktiv werden, was eine wichtige Grundlage für die Weiterentwicklung von Plattformen und gezielten Kommunikationsstrategien darstellt.
Abb. 5.9 Zeitverlauf der Baumbewässerung (Quelle: eigene Ausarbeitung)#
5.5.1. Benutzeroberfläche (UI)#
Zunächst fügen Sie einen weiteren Menüpunkt zur Navigation hinzu, um den Zeitverlauf-Tab zugänglich zu machen.
Navigation in der Seitenleiste
dashboardSidebar(
sidebarMenu( id = "sidebarMenu",
menuItem("Startseite", tabName = "start", icon = icon("home")),
menuItem("Karte", tabName = "map", icon = icon("map")),
# NEU: Menüpunkt für die Zeitverlauf hinzufügen
menuItem("Zeitverlauf", tabName = "stats", icon = icon("bar-chart"))
)
)
Inhaltsbereich: Diagramm und Filtern#
Der Inhaltsbereich enthält das Liniendiagramm sowie Filteroptionen, mit denen Nutzer:innen die Darstellung anpassen können.
Code
tabItem(
tabName = "stats",
fluidRow(
box(
title = tagList(
"Trend der Bewässerung je Pflanzjahr",
div(
actionButton("info_btn_tdbjp", label = "", icon = icon("info-circle")),
style = "position: absolute; right: 15px; top: 5px;"
)
),
status = "primary",
solidHeader = TRUE,
width = 12,
fluidRow(
column(
width = 6,
sliderInput(
"trend_year",
"Pflanzjahre filtern:",
min = 1800,
max = max(df_merged$pflanzjahr, na.rm = TRUE),
value = c(1800,
max(df_merged$pflanzjahr, na.rm = TRUE)),
step = 1,
sep = ""
)
),
column(
width = 6,
selectInput(
"trend_bezirk_pj",
"Bezirk auswählen:",
choices = c("Alle Bezirke", sort(unique(df_merged$bezirk))),
selected = "Alle Bezirke",
multiple = TRUE
)
)
),
plotlyOutput("trend_water", height = "500px")
)
)
)
Erklärung des Codes
Struktur des Inhaltsbereichs:
box(...)gruppiert alle Elemente visuelltitleenthält die Überschrift und einen Info-Buttonstatus = "primary"bestimmt die Farbewidth = 12bedeutet volle Seitenbreite
Filterelemente:
sliderInput("trend_year", ...)– ein Schieberegler zur Auswahl eines Pflanzjahr-BereichsAls Min-Wert ist das Jahr 1800 gewählt. Als Max-Wert wird das aktuellste Pflanzjahr aus dem Datensatz ermittelt
Nutzer:innen können gezielt nur junge Bäume, nur Altbestand oder ein bestimmtes Jahrzehnt untersuchen
selectInput("trend_bezirk_pj", ...)– ein Dropdown zur Bezirksauswahlmultiple = TRUEermöglicht die Auswahl mehrerer Bezirke gleichzeitigStandardwert ist „Alle Bezrike“
Visualisierung:
plotlyOutput("trend_water", ...)– reserviert Platz für das interaktive DiagrammDie tatsächliche Grafik wird im Server erzeugt
Plotly ermöglicht Zoomen, Tooltips und interaktive Achsen
Diese Struktur gibt Nutzer:innen volle Kontrolle: Sie können sowohl den Zeitraum als auch die betrachteten Bezirke frei anpassen und so gezielt nach Mustern suchen.
5.5.2. Server#
Daten vorbereiten und filtern#
Zunächst müssen Sie die Rohdaten so vorbereiten, dass nur relevante Einträge berücksichtigt werden. In diesem Fall Bäume, die tatsächlich gegossen wurden und für die ein Pflanzjahr bekannt ist.
Code
# Trend: Bewässerung nach Pflanzjahr
output$trend_water <- renderPlotly({
req(input$sidebarMenu == "stats")
filtered_data <- df_merged %>%
filter(!is.na(bewaesserungsmenge_in_liter)) %>%
filter(!is.na(pflanzjahr))
if (!"Alle Bezirke" %in% input$trend_bezirk_pj && length(input$trend_bezirk_pj) > 0) {
filtered_data <- filtered_data %>%
filter(bezirk %in% input$trend_bezirk_pj)
}
filtered_data <- filtered_data %>%
filter(pflanzjahr >= input$trend_year[1] & pflanzjahr <= input$trend_year[2])
Erklärung des Codes
Grundfilterung:
req(input$sidebarMenu == "stats")– stellt sicher, dass der Plot nur berechnet wird, wenn der Tab „Zeitverlauf“ aktiv ist.filter(!is.na(bewaesserungsmenge_in_liter))– nur Bäume, die tatsächlich gegossen wurdenfilter(!is.na(pflanzjahr))– nur Bäume mit bekanntem Pflanzjahr
Bezirksfilter:
Wenn „Alle Bezirke“ ausgewählt ist → keine Einschränkung
Wenn bestimmte Bezirke ausgewählt wurden → behalte nur diese
Pflanzjahr-Filter:
input$trend_year[1]ist der untere Wert des Schiebereglersinput$trend_year[2]ist der obere WertSo können Nutzer:innen gezielt z. B. nur Bäume aus den Jahren 1950–2020 betrachten
Durch diese mehrstufige Filterung erhälen Sie einen sauberen Datensatz, der genau die Bäume enthält, die für die aktuelle Analyse relevant sind.
Bewässerungsmenge pro Pflanzjahr berechnen#
Jetzt aggregieren Sie die Daten: Für jedes Pflanzjahr wird die gesamte gegossene Wassermenge sowie die Anzahl der bewässerten Bäume berechnet.
Code
plot_data <- filtered_data %>%
group_by(pflanzjahr) %>%
summarize(
total_water = sum(bewaesserungsmenge_in_liter, na.rm = TRUE),
count_trees = n_distinct(gml_id)
) %>%
ungroup()
Erklärung des Codes
group_by(pflanzjahr)gruppiert die Daten nach Pflanzjahrsummarize(...)berechnet für jede Gruppe:total_water– die Summe aller gegossenen Litercount_trees– die Anzahl unterschiedlicher Bäume (n_distinctzählt jeden Baum nur einmal)
ungroup()löst die Gruppierung wieder auf
Eine Tabelle mit drei Spalten: Pflanzjahr, Gesamtwassermenge, Anzahl Bäume
Diese Aggregation beantwortet die zentrale Frage: „Welche Baumjahrgänge wurden besonders intensiv bewässert?“
Liniendiagramm erstellen#
Mit den aggregierten Daten erstellen Sie nun ein Liniendiagramm, das den Trend über die Pflanzjahre zeigt.
Code
plot <- ggplot(plot_data, aes(x = pflanzjahr, y = total_water)) +
geom_line(color = "#2E86AB", size = 1) +
geom_point(
aes(text = paste0("Pflanzjahr: ", pflanzjahr,
"<br>Gesamtwasser: ", format(total_water, big.mark = ".", decimal.mark = ","), " L",
"<br>Anzahl Bäume: ", count_trees)),
size = 2, color = "#2E86AB"
) +
theme_minimal() +
labs(
x = "Pflanzjahr",
y = "Gesamtbewässerung (Liter)"
) +
theme(panel.grid.minor = element_blank())
ggplotly(plot, tooltip = "text") %>%
layout(hovermode = "closest")
})
Erklärung des Codes
ggplot2-Grundstruktur:
aes(x = pflanzjahr, y = total_water)definiert, was auf den Achsen dargestellt wirdgeom_line(...)zeichnet die Verbindungslinie zwischen den Datenpunktengeom_point(...)setzt Punkte auf jeden Datenpunktaes(text = ...)definiert, was beim Überfahren mit der Maus angezeigt wird:Pflanzjahr
Gesamtwassermenge (formatiert mit Tausenderpunkten)
Anzahl der bewässerten Bäume
theme_minimal()sorgt für ein aufgeräumtes Designlabs(...)beschriftet die Achsen
Interaktivität durch Plotly:
ggplotly(...)wandelt das statische ggplot in ein interaktives Plotly-Diagramm umtooltip = "text"zeigt die zuvor definierten Tooltips beim Hover anlayout(hovermode = "closest")sorgt dafür, dass immer der nächstgelegene Datenpunkt angezeigt wird
Durch diese Kombination aus ggplot2 und Plotly entsteht ein Diagramm, in dem Nutzer:innen hineinzoomen, Achsen verschieben und präzise Werte ablesen können.
5.5.3. Reflexion#
Der dargestellte Trend der Bewässerungsmenge je Pflanzjahr zeigt zwar über den gesamten Zeitraum betrachtet einen grundsätzlich steigenden Verlauf, allerdings lässt sich kein klar lineares oder systematisches Muster erkennen. Stattdessen wirkt der Verlauf stark heterogen, mit ausgeprägten Spitzen und Einbrüchen in einzelnen Jahrgängen.
Diese Ausschläge könnten dafür sprechen, dass strukturelle Eigenschaften der Bäume (z.B. wie Alter, Größe und Wasserbedarf) eine wesentlich größere Rolle spielen als der zeitliche Trend selbst. Insbesondere wird sichtbar, dass jüngere Bäume, also jene mit einem neueren Pflanzjahr, deutlich häufiger und intensiver gegossen werden. Das deckt sich mit den fachlichen Erwartungen:
Jungbäume haben ein unterentwickeltes Wurzelsystem,
sind schlechter in der Lage, tiefere Bodenfeuchte zu erschließen,
und benötigen daher laut gärtnerischer Empfehlungen (vgl. z. B. Giess-den-Kiez) mehr Bewässerung, besonders in den ersten Jahren nach der Pflanzung.
Die beobachteten starken Peaks deuten daher möglicherweise weniger auf eine generelle Zunahme des Engagements im Zeitverlauf hin, sondern vielmehr auf eine Konzentration des Engagements auf besonders pflegeintensive Bäume.
Einordnung der Unsicherheiten#
Mehrere Faktoren schränken die Interpretierbarkeit des Trends ein:
Die Anzahl der Bäume je Pflanzjahr ist nicht konstant; einzelne Jahrgänge sind stark unter- oder überrepräsentiert.
Das Bewässerungsverhalten hängt zusätzlich vom lokalen Kontext (Bezirk, Freiwilligenaktivität) ab, der im Aggregat verschleiert wird.
Stark schwankende Jahrgangswerte könnten auch auf Einzelbäume mit extrem vielen Gießungen zurückzuführen sein.
Gesamter Code für diesen Schritt
# UI-Definition
ui <- dashboardPage(
dashboardHeader(title = "Gieß den Kiez Dashboard"),
dashboardSidebar(
sidebarMenu( id = "sidebarMenu",
# Code aus den vorherigen Schritten Startseite, Karte und Bewässerungsanalyse
menuItem("Startseite", tabName = "start", icon = icon("home")),
menuItem("Karte", tabName = "map", icon = icon("map")),
menuItem("Bewässerungsanalyse", tabName = "analysis", icon = icon("chart-area")),
# NEU: Navigation für den Zeitverlauf
menuItem("Zeitverlauf", tabName = "stats", icon = icon("bar-chart"))
)
),
dashboardBody(
tabItems(
# ... Code aus Startseite, Karte & Bewässerungsanalyse (tabItem für "start", "map" & "analysis") ...
# NEU: Inhaltsbereich für den Zeitverlauf
tabItem(
tabName = "stats",
fluidRow(
box(
title = tagList(
"Trend der Bewässerung je Pflanzjahr",
div(
actionButton("info_btn_tdbjp", label = "", icon = icon("info-circle")),
style = "position: absolute; right: 15px; top: 5px;"
)
),
status = "primary",
solidHeader = TRUE,
width = 12,
fluidRow(
column(
width = 6,
sliderInput(
"trend_year",
"Pflanzjahre filtern:",
min = 1800,
max = max(df_merged$pflanzjahr, na.rm = TRUE),
value = c(1800,
max(df_merged$pflanzjahr, na.rm = TRUE)),
step = 1,
sep = ""
)
),
column(
width = 6,
selectInput(
"trend_bezirk_pj",
"Bezirk auswählen:",
choices = c("Alle Bezirke", sort(unique(df_merged$bezirk))),
selected = "Alle Bezirke",
multiple = TRUE
)
)
),
plotlyOutput("trend_water", height = "500px")
)
)
)
)
)
)
# Server-Logik
server <- function(input, output, session) {
# ... Code aus Startseite, Karte & Bewässerungsanalyse (Hilfsfunktionen, filteredData, Leaflet, hist_bewaesserung etc.) ...
# NEU: Trend: Bewässerung nach Pflanzjahr
output$trend_water <- renderPlotly({
req(input$sidebarMenu == "stats")
filtered_data <- df_merged %>%
filter(!is.na(bewaesserungsmenge_in_liter)) %>%
filter(!is.na(pflanzjahr))
if (!"Alle Bezirke" %in% input$trend_bezirk_pj && length(input$trend_bezirk_pj) > 0) {
filtered_data <- filtered_data %>%
filter(bezirk %in% input$trend_bezirk_pj)
}
filtered_data <- filtered_data %>%
filter(pflanzjahr >= input$trend_year[1] & pflanzjahr <= input$trend_year[2])
plot_data <- filtered_data %>%
group_by(pflanzjahr) %>%
summarize(
total_water = sum(bewaesserungsmenge_in_liter, na.rm = TRUE),
count_trees = n_distinct(gml_id)
) %>%
ungroup()
plot <- ggplot(plot_data, aes(x = pflanzjahr, y = total_water)) +
geom_line(color = "#2E86AB", size = 1) +
geom_point(
aes(text = paste0("Pflanzjahr: ", pflanzjahr,
"<br>Gesamtwasser: ", format(total_water, big.mark = ".", decimal.mark = ","), " L",
"<br>Anzahl Bäume: ", count_trees)),
size = 2, color = "#2E86AB"
) +
theme_minimal() +
labs(
x = "Pflanzjahr",
y = "Gesamtbewässerung (Liter)"
) +
theme(panel.grid.minor = element_blank())
ggplotly(plot, tooltip = "text") %>%
layout(hovermode = "closest")
})
# NEU: Info button observer
observeEvent(input$info_btn_tdbjp, {
showModal(modalDialog(
title = "Information: Trend der Bewässerung je Pflanzjahr",
HTML("
<p>Diese Grafik zeigt die <strong>Gesamtbewässerungsmenge nach Pflanzjahr</strong> der Bäume.</p>
<p><strong>Hintergrund:</strong> Junge und sehr alte Bäume benötigen typischerweise mehr Wasser als Bäume mittleren Alters.</p>
<ul>
<li>Junge Bäume (kürzlich gepflanzt) haben noch flache Wurzelsysteme</li>
<li>Sehr alte Bäume können geschwächt sein und mehr Unterstützung brauchen</li>
<li>Bäume mittleren Alters sind oft selbstständiger</li>
</ul>
<p><strong>Verwendung:</strong></p>
<ul>
<li>Nutzen Sie die Filter, um bestimmte Jahrgänge oder Bezirke zu analysieren</li>
<li>Bewegen Sie die Maus über die Punkte für Details</li>
<li>Mehrere Bezirke können gleichzeitig ausgewählt werden</li>
</ul>
<p><strong>Ergebnis:</strong> Die Daten zeigen keine wesentlichen Auffälligkeiten - das Pflanzjahr scheint kein entscheidender Faktor für das Bewässerungsengagement zu sein.</p>
"),
easyClose = TRUE,
footer = modalButton("Schließen")
))
})
}
shinyApp(ui = ui, server = server)
Übung#
Bei der gewählten Form der Darstellung handelt es sich um ein klassisches Liniendiagramm (Line Graph).
Laut dem The Data Visualization Catalogue eignen sich Liniendiagramme gut, um quantitative Werte über ein kontinuierliches Intervall oder einen bestimmten Zeitraum darzustellen. Sie werden am häufigsten eingesetzt, um Trends aufzuzeigen und zu analysieren, wie sich Daten über die Zeit verändert haben.
Die visuelle Stärke dieser Darstellung liegt in ihrer einfachen Lesbarkeit:
Ein Aufwärtstrend (steigende Linie) zeigt intuitiv eine Zunahme der Werte (in unserem Fall: mehr gegossene Liter für bestimmte Pflanzjahre).
Ein Abwärtstrend (fallende Linie) signalisiert eine Abnahme.
Der gesamte Verlauf der Linie über das Diagramm hinweg erzeugt Muster, die verborgene Trends innerhalb eines Datensatzes sichtbar machen.
Unser Diagramm nutzt auf der y-Achse den quantitativen Wert (die aggregierte Wassermenge in Litern) und auf der x-Achse eine chronologische Abfolge (die Pflanzjahre), was exakt den Best Practices für Liniendiagramme entspricht.
Das Liniendiagramm ist jedoch nicht die einzige Möglichkeit, Daten über einen bestimmten Zeitraum hinweg darzustellen. Es gibt viele weitere Visualisierungsmethoden, die speziell darauf ausgelegt sind, Veränderungen im Zeitverlauf zu kommunizieren.
Nutzen Sie den The Data Visualization Catalogue (Filter: „Search by Function“ > „Over Time“), um alternative Darstellungsformen zu recherchieren.
Beispiele für solche Alternativen sind:
Area Graph (Flächendiagramm)
Bar Chart (Säulendiagramm)
Candlestick Chart (Kerzendiagramm)
… und viele mehr.
Überlegen Sie sich, welche dieser Alternativen sich ebenfalls für die Darstellung unserer Bewässerungsdaten eignen könnten und wo deren Vor- und Nachteile gegenüber dem klassischen Liniendiagramm liegen.
Überleitung zum nächsten Analyse-Schritt#
Die bisherige Betrachtung nach Pflanzjahren legt nahe, dass das Engagement nicht nur zeitlich, sondern vor allem strukturell geprägt ist, und das insbesondere durch Unterschiede im Alter der Bäume und damit verbundenem Wasserbedarf. Um diese Muster besser zu verstehen, ist es sinnvoll, das Bewässerungsverhalten im Kontext der räumlichen und biologischen Baumstruktur zu betrachten.