10 Ausblick: Generierung von dynamischen Reports

Zur Generierung dynamischer Berichte ist ein Wechsel des zu erzeugenden Dateiformats erforderlich. Das Ziel ist dann nicht mehr die Erzeugung eines Berichts, der in einem Textverarbeitungsprogramm geöffnet oder editiert werden kann, sondern die Erzeugung eines Berichts, der in der Regel über einen Webbrowser angezeigt wird. Auch in diesem Fall gibt es verschiedene Möglichkeiten dieses Ziel zu erreichen. So können entweder Berichte in einem HTML-Format erzeugt werden oder sogenannte Dashboards (beispielsweise mit shiny (Chang et al. 2021) und shinydashboard (Chang and Borges Ribeiro 2021)) erzeugt werden. Während erstere gegenüber den zuvor behandelten Berichtsformaten vor allem Vorteile hinsichtlich der Anzeige der Berichte auf verschiedenen Endgeräten sowie hinsichtlich der Interaktivität bieten, vereinen letztere diese Vorteile mit der Option auch Input von Userinnen und Usern zu berücksichtigen, sodass beispielsweise Texte in Abhängigkeit von der Auswahl der Userinnen und Usern angezeigt werden.

10.1 Generierung eines dynamischen Balkendiagramms

In beiden Varianten bietet es sich an, für die Erzeugung von Abbildungen das Paket plotly (Sievert 2020) statt des Pakets ggplot2 zu nutzen. Unter Nutzung dieses Pakets ist es den Userinnen und Usern möglich, mit bereitgestellten Abbildungen zu interagieren und beispielsweise einzelne Elemente zu selektieren, Ausschnitte der Abbildung zu betrachten oder in die Abbildung hineinzuzoomen. Eine Übersicht über die zahlreichen Möglichkeiten, die dieses Paket zur Visualisierung bietet, findet sich – inklusive Beispielcode zur Umsetzung in eigenen Projekten – online unter: https://plotly.com/r/. Trotz dieser umfangreichen Onlinedokumentation soll an dieser Stelle exemplarisch die Übersetzung des zuvor mit ggplot2 erstellten Balkendiagramms in plotly kurz beschrieben werden.

Erneut wird der zuvor erzeugte Datenframe data_plot_lf genutzt. Hier sind in diesem Fall keinerlei Modifikationen erforderlich. Zunächst wird dann mit dem Befehl plot_ly() die Erstellung einer Abbildung begonnen. Der Unterbefehl type= gibt dann vor, welche Art von Abbildung erzeugt wird – in diesem Fall ein Balkendiagramm. Die Unterbefehle x= und y= regeln, welche Variablen aus dem Datenframe für die beiden Achsen der Abbildung herangezogen werden sollen. Mit dem Unterbefehl name= wird definiert, welche Angaben für die Legende und die Differenzierung der einzelnen Balken verwendet werden.

plot_ly(data_plot_lf, x = ~name, y = ~value, name = ~name, type = 'bar')

Ausgehend von dieser Basisvariante kann eine Abbildung erzeugt werden, welche der zuvor mit ggplot2 erzeugten Abbildung optisch sehr ähnlich ist, jedoch über dynamische Funktionen verfügt. Zunächst wird die Abbildung mit dem Unterbefehl orientation=“h” in ein horizontales Balkendiagramm überführt. Zudem können im Unterbefehl name= explizite Vorgaben für die Beschriftung der Legende gemacht werden – in diesem Fall werden die Bezeichnungen der einzelnen Schuljahre angegeben. Nicht zuletzt ist zu beachten, dass durch das Kippen des Diagrammes ebenso die Angaben für Achsen getauscht werden müssen. Dies wird hier ergänzt durch eine Änderung der Reihenfolge der Schuljahre (Unterbefehl fct_reorder()), sodass das aktuellste Schuljahr als unterster Balken angezeigt wird.

plot_ly(data_plot_lf, y = ~fct_reorder(name, desc(name)), x = ~value, name = c("2017/18","2018/19","2019/20"), type = 'bar', orientation = "h")

Nach diesem Schritt können weitere optische Anpassungen vorgenommen werden. So werden über die Unterbefehle color= und colors= die Farben der einzelnen Balken bestimmt. Auch hier erfolgt eine Wiederverwendung der zuvor definierten Farben über das Objekt color_3_rev. Zudem werden über den Unterbefehl text= die Balkenbeschriftungen erzeugt, deren Position über den Unterbefehl textposition= bestimmt wird. Der Unterbefehl hoverinfo= regelt darüber hinaus, welche Informationen angezeigt werden, wenn mit der Maus auf einen Balken gezeigt wird (sogenannte Mouseover-Funktion).

plot_ly(data_plot_lf, y = ~fct_reorder(name, desc(name)), x = ~value, name = c("2017/18","2018/19","2019/20"), type = 'bar', orientation = "h", 
        color = ~name, colors = color_3_rev,
        text = ~percent(value, accuracy = 0.1), textposition='outside', 
        hoverinfo = "name")

Im letzten Schritt werden Vorgaben über den Unterbefehl layout() für das Layout der beiden Achsen gemacht. So wird der Titel der x-Achse entfernt und vorgegeben, dass Prozentwerte ausgewiesen werden sollen. Für die y-Achse wird entsprechend definiert, dass auch diese titellos ist und keine Labels an den Balken platziert werden sollen, da diese bereits über die Legende eindeutig bestimmbar sind.

plot_ly(data_plot_lf, y = ~fct_reorder(name, desc(name)), x = ~value, name = c("2017/18","2018/19","2019/20"), type = 'bar', orientation = "h", 
        color = ~name, colors = color_3_rev,
        text = ~percent(value, accuracy = 0.1), textposition='outside', 
        hoverinfo = "name") %>%
  layout(xaxis = list(title = "", rangemode = "tozero",  zerolinecolor = toRGB("lightgray"), tickformat = "1%", hoverformat = ".1%"),
         yaxis = list(title = "", showticklabels = FALSE))

10.2 Erstellung eines HTML-Berichts

Die Überführung der Inhalte aus einem statischen Bericht (beispielsweise WORD oder PDF) in einen dynamischen Bericht stellt nur einen geringen Aufwand dar. So lässt sich im YAML-Header das entsprechende Output-Format anpassen. Dazu muss lediglich die folgende Codezeile und gegebenenfalls die Endung der zu erzeugenden Datei (in .html) angepasst werden:

output: word_document # ersetzen durch
output: html_document

Einen anderen Weg stellt die Erzeugung einer neuen R Markdowndatei dar (siehe dazu den Abschnitt Erstellen einer neuen R Markdowndatei), wobei im Dialogfeld entsprechend html zu wählen ist. Nachdem dieses Dokument erzeugt wurde, können die Inhalte per Copy-and-paste übertragen und im neu erzeugten Dokument genutzt werden. Zu beachten ist jedoch, dass eine solche reine Änderung des Berichtsformats nicht mit einer automatischen Dynamisierung des Berichts einhergeht. Vielmehr eröffnet dies nur einen anderen Zugangsweg. Für die durchgängige Dynamisierung des Berichts sind, wie zuvor anhand einer Abbildung exemplarisch beschrieben, Anpassungen erforderlich, die teilweise erheblichen Arbeitsaufwand bedeuten können. Insofern sollte die Entscheidung für ein Berichtsformat vor der Arbeit an dessen Umsetzung mit R Markdown gefällt werden.

10.3 Erstellung eines Dashboards

Zur Erstellung eines Dashboards, welches gegenüber einem HTML-Bericht noch zusätzliche dynamische Features besitzt, kann auf die Pakete shiny (Chang et al. 2021) und shinydashboard (Chang and Borges Ribeiro 2021) zurückgegriffen werden. Diese ermöglichen die Bereitstellung eines Formats, dass interaktiv auf die Eingaben der Userinnen und User reagiert. Idealerweise sollte zu diesem Zweck ein entsprechender Server genutzt werden, auf welchem das Dashboard nach Abschluss der Entwicklung bereitgestellt wird. Die Entwicklung des Dashboards kann jedoch lokal unter Nutzung von R und RStudio erfolgen.

Dazu ist eine neue Datei für eine Shiny Web App zu erzeugen, in welcher das Dashboard definiert wird. Dies kann abermals über das Menü (filenew fileShiny Web App ) oder das Symbol zur Anlage einer neuen Datei erfolgen. Im erscheinenden Dialogfenster ist anschließend der Speicherort der Datei sowie der zugehörige Name der App anzugeben. Ebenso kann gewählt werden, ob das gesamte Dashboard in einer Datei (app.R) oder in zwei Dateien (ui.R sowie server.R) gespeichert werden soll. Bei kleineren Dashboards bietet es sich an, eine Datei zu nutzen, während größere Projekte in unterschiedlichen Dateien ausgelagert werden können. Aus diesem Grund wird hier beispielhaft mit einer einzelnen Datei (app.R) gearbeitet.

Nach dem Öffnen dieser Datei fällt auf, dass diese schon mit lauffähigem Code befüllt ist, der die Features eines Dasboards in den Grundzügen veranschaulicht. So kann mit einem Klick auf den Button Run App der Code ausgeführt werden und das Dashboard angezeigt werden. Danach wird durch R ein lokaler Server gestartet, der das Dashboard anzeigt. Der Standardcode veranschaulicht mittels eines Sliders und einem Histogramm, wie eine Anpassung der Abbildung auf die Vorgaben der Userinnen und User reagiert. Zum Stoppen des Servers ist entweder das Browserfenster zu schließen oder auf das Stopp-Zeichen in RStudio zu klicken.

Um nun die Standarddatei auf die hier verwendeten Beispieldaten anzupassen, sind folgende Schritte erforderlich.

Zunächst kann eine Zeile eingefügt werden, in welcher der Code zur Aufbereitung und Auswertung der Daten aufgerufen wird. Diese Zeile ist vor der ui des Dashboards einzufügen. Gleichzeitig ist zu beachten, dass diese Datei im selben Ordner wie die Datei app.R abgelegt sein muss.26 Alternativ können das Laden der Daten sowie alle Datenaufbereitungen auch direkt in der Datei app.R erfolgen.

source("Aufbereitung.R")

Wird die App mit dieser Ergänzung ausgeführt, ist der Zugriff auf die in dem Code erzeugten Objekte möglich. Gleichwohl ist noch eine Einbindung derselben in das Dashboard erforderlich. Zuvor kann bereits der Titel des Dashboards angepasst werden, indem die Codezeile mit dem tilePanel() angepasst wird.

titlePanel("Beispiel für ein Dashboard"),

Anschließend kann in der Sidebar der ui die Selektion angepasst werden, sodass nicht mehr eine Zahl auf einem Zahlenstrahl, sondern eine Schulform über ein Dropdown-Menü ausgewählt werden kann. Dazu wird im Abschnitt sidebarPanel() der sliderInput() durch ein selectInput() ersetzt. Diese Selektionsmöglichkeit bildet die Basis für die dynamischen Abbildungen.

selectInput("sfo", "Schulform:",
            c("Gymnasium" = "gym",
              "Stadtteilschule" = "sts",
              "Grundschule" = "gs",
              "Sonderschule" = "so")),

Danach ist im Abschnitt mainPanel() der ui des Dashboards im Aufbereitscode erzeugte Abbildungen mit ggplot2 und plotly sowie eine Tabelle einzutragen, sodass diese im Dashboard angezeigt werden kann. Mit dem Befehl h3() wird zudem eine Überschrift (der dritten Gliederungsebene) in einer definierten Farbe eingefügt.

#Abbildung ggplot2
h3("Abbildung für ausgewählte Schulform (ggplot2)", style='color:#005ca9'),
plotOutput("plot_lf_filtered"),
#Abbildung plotly
h3("Abbildung für ausgewählte Schulform (plotly)", style='color:#005ca9'),
plotlyOutput("plotly_lf_filtered"),
#Tabelle
h3("Tabelle der Daten", style='color:#005ca9'),
tableOutput("table_data")

Gleichzeitig sind im Abschnitt für die server logic des Dashboards die Daten so anzupassen, dass die Tabelle und die Abbildung entsprechend des Inputs der Userinnen und User angezeigt werden. Zum Anzeigen einer Tabelle ist der Befehl renderTable({}) zu nutzen, in welchem das anzuzeigende Objekt – in diesem Fall der Datenframe, der in der Abbildung visualisiert wird – definiert wird. Unter Nutzung des zuvor entwickelten Codes ergibt sich der folgende Beispielscode. Über den Unterbefehl width= wird zusätzlich definiert, dass die Anzeige die gesamte Breite des Dashboards nutzen soll.

output$table_data <- renderTable({
  Tabelle <- dkf %>% filter(D19_Schulform_akt %in% input$sfo) %>%
    group_by() %>%
    summarize(across(contains("LF_1"), ~ sum(.[. == 1])/n())) %>%
    pivot_longer(., cols = contains("LF_1")) %>%
    rename("Schuljahr" = "name", "Anteil mit Lernföderbedarf" = "value")
  Tabelle$Schuljahr <- c("2017/18", "2018/19", "2019/20")
  Tabelle <- as.data.frame(Tabelle)
  }, 
  digits = 3, width = "100%")

In ähnlicher Weise kann mit Zuhilfename des zuvor entwickelten Codes für ein Balkendiagramm mit ggplot2 ein dynamisches Diagramm, welches auf die durch die Userinnen und User gesetzten Filter dynamisch angepasst wird, erzeugt werden. Dazu wird zunächst ein neues Objekt erzeugt, welches die angepassten Daten enthält. Hierzu werden der Befehl reactive({}) und der zuvor für die Erzeugung das Datenframes für die Abbildung entwickelte Code genutzt.

data_filtered_sfo <- reactive({
  dkf %>% filter(D19_Schulform_akt %in% input$sfo) %>%
    group_by() %>%
    summarize(across(contains("LF_1"), ~ sum(.[. == 1])/n())) %>%
    pivot_longer(., cols = contains("LF_1"))
    })

Der auf diese Weise erzeugte dynamische Datenframe wird im Befehl renderPlot({}) genutzt um die gewünschte Abbildung zu erzeugen.

output$data_plot_lf <- renderPlot({
  r_plot <- ggplot(data_filtered_sfo(),
                   aes(x=name, y=value, fill=name))   
  r_plot + geom_bar(stat = "identity") +
    scale_fill_manual(labels = c("Sj. 2017/18","Sj. 2018/19","Sj. 2019/20"), values = c("#B5D8FA", "#2E7FD2", "#003063")) +
    coord_flip() + 
    theme_minimal() + 
    theme(axis.title.x=element_blank(), axis.title.y=element_blank(), 
          legend.position = "right", legend.title = element_blank(),
          axis.text.y = element_blank(),
          plot.caption = element_text(hjust = 0),
          plot.background = element_rect(colour = "black", fill=NA, size=1),
          panel.grid = element_blank()) + 
    labs(fill = "Schuljahr", caption = "Anmerkung: Sprachförderbedarf Jg. 1-10, ohne IVK und Basisklassen; Lernförderbedarf Jg. 1-13, nur Regelklassen; Quelle: DiViS") +
    scale_y_continuous(labels = percent_format(accuracy = .1)) +
    geom_text(aes(label=percent(value, accuracy = .1)), vjust=0.25, hjust = -.2, size=3, colour = "black") +
    guides(fill = guide_legend(reverse = T)) +
    ggtitle("Schülerinnen und Schüler mit Lernförderbedarf, Schuljahre 2017/18 bis 2019/20, 1. Hj.")
    })

In ähnlicher Weise kann über den Befehl auch eine mit plotly erstellte Abbildung in einem Dashboard genutzt werden. Dazu ist entsprechend der Befehl renderPlotly({}) zu nutzen.

output$plotly_lf_filtered <- renderPlotly({
  plot_ly(data_filtered_sfo(), x = ~name, y = ~value, name = c("2017/18","2018/19","2019/20"), type = 'bar', 
          color = ~name, colors = c("#B5D8FA", "#2E7FD2", "#003063"),
          text = ~percent(value, accuracy = 0.1), textposition='outside', hoverinfo = "name") %>%
    layout(yaxis = list(title = "", rangemode = "tozero",  zerolinecolor = toRGB("lightgray"), tickformat = "1%", hoverformat = ".1%"),
           xaxis = list(title = "", showticklabels = FALSE))
    })

References

Chang, Winston, and Barbara Borges Ribeiro. 2021. Shinydashboard: Create Dashboards with Shiny. http://rstudio.github.io/shinydashboard/.
Chang, Winston, Joe Cheng, JJ Allaire, Carson Sievert, Barret Schloerke, Yihui Xie, Jeff Allen, Jonathan McPherson, Alan Dipert, and Barbara Borges. 2021. Shiny: Web Application Framework for r. https://shiny.rstudio.com/.
Sievert, Carson. 2020. Interactive Web-Based Data Visualization with r, Plotly, and Shiny. Chapman; Hall/CRC. https://plotly-r.com.

  1. Alternativ kann auch ein Dateipfad zu einer bestimmten Datei angegeben werden – eine Ablage an unterschiedlichen Orten ist also grundsätzlich möglich, jedoch nicht angeraten.↩︎