Courtesy of pxhere

Übersicht

Fragestellung

In diesem Projekt beschäftigen wir und mit dem shiny-Paket in R. Shiny ist ein R-internes Paket, welches es ermöglicht, interaktive HTML-basierte Websites oder Web Apps einfach mit R zu erstellen.Darüber hinaus kannHTML-Code (und CSS) direkt in R eingebunden werden. Wir wollen hierbei veranschaulichen, inwieweit R verschiedene Programmiersprachen miteinander verbinden kann und inwieweit daraus komplexere Ergebnisse entstehen können. Dieses Projekt befasst sich demnach mit folgender Frage: “Wie erstellt man mithilfe von R interaktive Websites/Apps?”

Zielsetzung

Dieses Projekt soll dir vermitteln, wie man einfachere interaktive Websites mithilfe von R, insbesondere dem shiny-Paket, und optional HTML und CSS erstellen kann. Zunächst werden wir uns hierbei mit den Basics beschäftigen und mit ein wenig Übung kann man die Grundbausteine interaktiver Websites verstehen, anwenden und umsetzen. Auf der Website von shiny gibt es einige Beispiele für die vielfältigen Anwendungsmöglichkeiten, welche du dir hier anschauen kannst. Am Ende dieser Projektübersicht erstellen wir ein Beispiel, um dir die Grundbausteine interaktiver Websites näherzubringen. So sieht unser Beispiel aus.

Vorbereitung

Das folgende Projekt soll sich mit der Erstellung von eigenen interaktiven Websites befassen. Dafür werden beispielhaft die Daten und Ergebnisse aus Projekt 1, sowie die Ergebnisse aus Projekt 5 verwendet und so verändert, dass sie einige interaktive Elemente beinhalten.

Bevor du damit anfangen kannst, solltest du dir zunächst einen Überblick über das shiny-Paket und dessen Anwendung in R verschaffen. Dafür bietet sich in erster Linie die zum Paket gehörige Website an, die du hier finden kannst. Für Anfänger:innen hält diese auch ein Tutorial bereit, das sich mit den Grundsätzen von shiny auseinandersetzt. Eine gute Übersicht über die grundsätzlichen Befehle erhältst du hier in Form eines Cheatsheets oder über die folgende Bilder-Galerie aus dem bereits erwähnten Tutorial:

Beispiel

Damit du einen ersten Eindruck der Anwendungsmöglichkeiten von shiny bekommen kannst, stellen wir dir hier ein kurzes Beispiel vor, das sich hauptsächlich mit den Basics der Programmiersprache befasst. Mitunter bekommst du dann auch eine bessere Vorstellung davon, was überhaupt mit “Interaktivität” gemeint ist.

Für das Beispiel soll eine bestimmte Anzahl an Zufallszahlen aus der Normalverteilung gezogen und die Daten dann in einem Histogramm dargestellt werden. Dabei werden die Stichprobengröße, der Mittelwert der Normalverteilung, die Standardabweichung der Normalverteilung und die Anzahl der Balken des Histogramms durch die Anwender:innen manipulierbar sein. Darüber hinaus soll für die Darstellung wählbar sein, ob die Normalverteilungskurve und ein Maß der zentralen Tendenz (für die gezogene Stichprobe) angezeigt werden sollen.

Wie du vielleicht bereits im Tutorial von shiny gesehen hast, bestehen shiny-Apps aus einem User Interface (ui) und dem im Hintergrund laufenden R-Code (server). Bevor du also einfach die jeweiligen Codes für beide Teile siehst, sollst du zunächst sehen, was du prinzipiell für die Umsetzung des Beispiels alles benötigen wirst.

User Interface (ui)

Das User Interface ist, wie es der Name schon sagt, der Teil der Website, den die Anwender:innen zu Gesicht bekommen. In diesem Teil geht also es weniger darum, wie einzelne Inhalte entstehen, sondern darum, aus welchen Elementen die Website bestehen soll und wie diese angeordnet sein sollen.

Wie bereits erwähnt, soll diese Website die Anwender:innen dazu befähigen, die Stichprobengröße, den Mittelwert, die Standardabweichung und die Anzahl der Balken auszuwählen. Außerdem sollen sie bestimmen können, ob ein Maß der zentralen Tendenz und die Normalverteilungskurve abgebildet werden sollen. Dafür benutzen wir zwei Schieberegler: einen für die Stichprobengröße und einen für die Anzahl der Balken. Des Weiteren brauchen wir ein kleines Auswahlmenü für das Maß der zentralen Tendenz, jeweils ein Zahlen-Input-Feld für Mittelwert und Standardabweichung und Radiobuttons für das Hinzufügen der Normalverteilungskurve. Zusätzlich kann man hier auch noch einen ActionButton einsetzen, um Aktualisierungen des Outputs (Histogramm) manuell auslösen zu können, sobald man bestimmte Eingaben vorgenommen hat. Letztlich muss man noch bestimmen, wo das Histogramm ausgegeben werden soll und schon ist man mit dem User Interface fertig. Zumindest fast… man hat zwar alle Bestandteile zusammen, doch diese müssen auch noch angeordnet werden.

Der fertige R-Code könnte letztlich folgendermaßen aussehen:

ui <- fluidPage(
  titlePanel(
    title = em(strong('Beispiel für die Übersicht in Projekt 7')),
    windowTitle = 'Beispiel für die Übersicht in Projekt 7'),
  hr(),
  plotOutput('Histogramm'),
  hr(),
  wellPanel(
    sliderInput(inputId = 'Stichprobengroesse',
                label = 'Stichprobengröße',
                value = 1000, min = 100, max = 10000, step = 100),
    sliderInput(inputId = 'Breaks',
                label = 'Balken im Histogramm',
                value = 10, min = 2, max = 100),
    fluidRow(
      column(6, numericInput(inputId = 'Mittelwert',
                             label = 'Mittelwert',
                             value = 100, min = -1000, max = 1000)),
      column(6, selectInput(inputId = 'Mass',
                            label = 'Maß der zentralen Tendenz (Stichprobe)',
                            choices = c('Kein Maß', 'Median', 'Mittelwert')))
    ),
    fluidRow(
      column(6, numericInput(inputId = 'Standardabweichung',
                             label = 'Standardabweichung',
                             value = 15, min = 0, max = 1000)),
      column(3, radioButtons(inputId = 'Normalverteilung',
                            label = 'Normalverteilungskurve einzeichnen',
                            inline = TRUE,
                            choices = c('Ja', 'Nein'),
                            selected = 'Nein')),
      column(3,
             br(),
             actionButton(inputId = 'Update',
                          label = 'Histogramm aktualisieren'))
    )
  ),
  hr()
)

Das User Interface kann man sich auch schon anschauen, indem man den folgenden Code ausführt:

server <- function(input, output, session) {

}

shinyApp(ui, server)
Wie man sehen kann, liegen das Layout und die Input-Objekte bereits vor und können manipuliert werden. Jedoch fehlt im User Interface (ui) der Output, mit dem wir uns nun im zweiten Teil (server) befassen werden.

Im nächsten Schritt erstellen wir den R-Code, der den Output (das Histogramm) in Abhängigkeit von den sechs Inputs erstellt. All das wird auf dem User Interface (ui) nicht sichtbar sein, sondern nur auf dem Server, in diesem Fall also dem Computer, auf dem die Website erstellt wird. Alle Operationen, die nicht auf der Website zu sehen sein sollen, müssen also in diesem zweiten Teil enthalten sein.

R-Code (server)

Die Frage, die sich zunächst stellt, ist: Worauf muss ich eigentlich achten? Was muss ich machen?

Für eine vollständige Website brauchen wir nur noch das Histogramm. Dieses ist in zweierlei Hinsicht abhängig von den Inputs: Zum einen wird der Datensatz durch die Inputs Stichprobengröße, Mittelwert und Standardabweichung beeinflusst, zum anderen wird die Abbildung selbst durch die Breaks, das Maß der zentralen Tendenz und die Normalverteilungskurve beeinflusst.

Der R-Code dazu sieht folgendermaßen aus:

server <- function(input, output, session) {
  rv <- reactiveValues(data = rnorm(1000, mean = 100, sd = 15))
  observeEvent(input$Update, {
    rv$data <- rnorm(input$Stichprobengroesse,
                     mean = input$Mittelwert,
                     sd = input$Standardabweichung)
  })
  output$Histogramm <- renderPlot({
    zentraleTendenz <- input$Mass
    Normalverteilungskurve <- input$Normalverteilung
    hist(rv$data, breaks = input$Breaks, freq = FALSE)
    if(Normalverteilungskurve == 'Ja'){
      curve(
        dnorm(x,
              mean = isolate(input$Mittelwert),
              sd = isolate(input$Standardabweichung)),
        add = TRUE, lwd = 3)
    }
    if(zentraleTendenz == 'Median'){
      abline(v = median(rv$data), lwd = 1, col = 'orange')
    } else if (zentraleTendenz == 'Mittelwert'){
      abline(v = mean(rv$data), lwd = 1, col = 'red')
    } else {}
  })
}

Wenn du den Code für beide Teile nun bei dir ausführst und die App dann mit shinyApp(ui, server) startest, wird sich ein neues Fenster auf deinem Gerät öffnen und die App mit diesem als Server ausführen. Probiere es einfach mal aus und versuche dann, durch Ausprobieren herauszufinden, wie die einzelnen Code-Zeilen das Endergebnis beeinflussen.

So sollte das Beispiel letztlich bei dir aussehen:

Hier kannst du die Website nochmals abrufen - wie du dann sehen wirst, ändert sich das Format je nach Breite des Fensters. Näheres dazu findest du möglicherweise selbst im Laufe des Projektes heraus - falls nicht, findest du in den Lösungen eine kurze Erklärung.

Das war es erst einmal mit der Einführung. Viel Spaß bei diesem Projekt!

Robin Mehler
Projekte