Reporting mit R The R Bootcamp |
from https://dilbert.com/
In diesem Practical übst du, dynamische Dashboards in Markdown zu erstellen. Ziel ist es dieses Dashboard zu erstellen.
Am Ende des Practicals wirst du wissen wie man:
leaflet
plottet.plotly
interaktiv macht.Öffne dein TheRBootcamp
R Projekt. Es sollte die Ordner 1_Data
, 2_Assets
und 3_Markdown
enthalten.
Öffne ein neues RMarkdown Skript und wähle das Template “Flex Dashboard” aus (siehe screenshot unten).
Speichere das neue Skript unter dem Namen dashboards_I_practical.Rmd
im 3_Markdown
Ordner.
Schreibe als Titel Dashboards I Practical
hinein.
Lösche alles unterhalb des setup
R chunks.
tidyverse
, plotly
, leaflet
, viridis
, htmltools
, lubridate
, patchwork
und flexdashboard
(letzteres sollte, wenn du das richtige Template ausgewählt hast, bereits im setup
Chunk als library()
Befehl eingefügt sein).# Lade Pakete
library(flexdashboard)
library(tidyverse)
library(plotly)
library(leaflet)
library(viridis)
library(htmltools)
setup
chunk den airbnb
Datensatz mit read_csv()
, so wie du das in den bisherigen Practicals auch gemacht hast.Beim Erstellen eines Dashboards ist es hilfreich, sich von Beginn an ein Layout zurechtzulegen, welches man dann Schritt für Schritt auffüllt. Eine Skizze oder zumindest eine bildliche/ konzeptuelle Vorstellung ist daher wichtig.
Öffne das Ziel-Dashboard Link in einem separaten Tab in deinem Browser. Wir werden während dieses Practicals immer wieder darauf verweisen.
Schau dir das Dashboard genau an, um einen Eindruck zu erhalten, was du nachbauen sollst, wie das Layout aussieht und welche Komponenten verwendet werden.
Setze zunächst das Seitenlayout des Dashboards auf. Füge drei Seiten hinzu: Übersicht der Airbnbs in Berlin
, Entwicklung über Zeit
und Bewertungen der Airbnbs
. Schreibe dazu die Titel in dein Markdown, unterhalb des R Setup chunks und füge eine Zeile von Gleichheitszeichen ========
unter jedem Titel ein.
TITEL
======================================================================
In flexdashboards
sind Seiten standardmässig spaltenweise ausgerichtet. Schaue dir das Dashboard nochmals an. Sind alle drei Seiten spaltenweise ausgerichtet?
Nur die zweite Seite ist spaltenweise ausgerichtet! Die erste Seite ist zeilenweise ausgerichtet, und die dritte Seite ist ein Storyboard. In einem Dashboard mit mehreren Seiten, kannst du jeweils nach dem Titel die Seitenausrichtung bestimmen. Schreibe für spaltenweise Ausrichtung {data-orientation=columns}
, für zeilenweise Ausrichtung {data-orientation=rows}
und für ein Storyboard {.storyboard}
jeweils nach dem Titel (aber auf derselben Zeile). Füge die entsprechende Ausrichtung nach den drei Titeln ein.
Nun beginne Seite 1 zu layoutieren. Du siehst, dass es zwei Zeilen gibt, eine mit den valueBoxes
, und eine mit der Karte. Die Zeilen werden mit Titel zweiter Ordnung (mit ----
) definiert. Füge zwei Zeilen, mit dem Namen Zeile 1
und Zeile 2
ein. Hier müssen keine sinnvollen Titel angegeben werden, da die Titel zweiter Ordnung nicht angezeigt werden.
Zeile X
----------------------------------------------------------------------
Wenn du das Dokument so knittest erhalten die beiden Zeilen gleich viel Platz. Die Karte soll jedoch mehr Platz erhalten. Füge dazu nach dem ersten Titel in derselben Zeile den folgenden Code ein: {data-height = 400}
. Damit wird die Zeilenhöhe in Pixeln angegeben; Zeile 2 füllt dann den restlichen Platz aus. Hinweis: Die Platzverteilung erfolgt erst, wenn die Komponenten gefüllt werden; wenn du das Dokument jetzt knittest, wird also Zeile 1 im Moment noch gleich hoch sein, wie Zeile 2.
Zeile 1 mit den valueBoxes
, ist wiederum in drei Spalten unterteilt, eine für jede valueBox
. Verwende Titel dritter Ordnung um die Spalten mit den Namen Superhosts
, Allstar
, und Preiswert
zu erstellen. Für diese Titel werden keine besonderen Zeichen verwendet, sondern wie gewohnt ###
.
In Zeile 2 (also unterhalb des nächsten Titels zweiter Ordnung) musst du nur einen Titel einfügen, ohne Titel dritter Ordnung klappt die automatische Grössenanpassung nicht. Gib “Karte” als Titel an, und füge direkt dahinter {.no-title}
ein; damit wird die Präsentation des Titels auf dem Dashboard unterdrückt.
Seite 1 ist vom Layout her fertig. Zeit, Seite zwei vorzubereiten. Schaue dir Vorlage dafür nochmals kurz an.
Diesmal besteht das Layout aus zwei Spalten. Überlege dir, wie du diese definieren würdest.
Du kannst wie bei Aufgabe C6 Titel zweiter Ordnung hinzfügen. Füge die zwei Spalten, diesmal mit den Titeln Spalte 1
und Spalte 2
, unter dem Titel der zweiten Seite hinzu (also nach der Zeile mit den Gleichheitszeichen).
Wie auf Seite 1, musst du auch hier noch die Spalten anpassen. Dort hattest du mit {data-height = 400}
die Höhe einer Zeile festgelegt. Die Breite einer Spalte kann analog mit {data-width = XXX}
festgelegt werden. Definiere, dass Spalte 2 200 Pixel breit ist; die Erste wird dann automatisch angepasst.
Nun fehlen nur noch die Titel der beiden Spalten. Verwende dazu Titel dritter Ordnung (###
) und nenne die linke Spalte Entwicklung der Berliner Airbnbs seit 2009
und die rechte Spalte Hintergründe
. Füge diese Titel dritter Ordnung jeweils unter dem Titel zweiter Ordnung (Spalte 1
bzw. Spalte 2
), welcher die Spalten definiert, ein.
So, nun fehlt nur noch das Layout der letzten Seite. Da es sich um ein Storyboard handelt, musst du keine Spalten oder Zeilen spezifizieren. Du kannst also direkt zu den Titeln dritter Ordnung übergehen.
Um die drei Abschnitte des Storyboards zu erstellen, verwende wiederum Titel dritter Ordnung (###
). Erstelle drei Abschnitte mit den Namen Gesamtrating
, Sauberkeit
, und Lage
.
In den Abschnitten des Storyboards soll es jeweils einen Hauptteil (links), sowie rechts eine schmalere Spalte mit Kommentaren haben. Definiere die Breite der kleineren Kommentarspalte, indem du nach jedem der drei Titel, aber auf derselben Zeile, {data-commentary-width=300}
einfügst.
Fast geschafft! Die Titel der Storyboardabschnitte sind noch etwas klein. Um sie zu vergrössern, musst du etwas HTML Syntax verwenden. Kopiere den untenstehenden Code und ersetze die Titel damit, und füge die Titelnamen von Aufgabe C16 in die XXX
des Codes ein.
<span style="font-size: 20px;">XXX</span>
Das Layout ist fertig. Nun geht es an den Inhalt. Beginne mit den valueBoxes
auf Seite 1. Um die erste valueBox
einzufügen, erstelle nach dem Superhost
Titel einen Code Chunk.
Berechne im erstellten R chunk zuerst die Anzahl im airbnb
Datensatz vorhandener Superhosts. Verwende dazu den untenstehenden Code.
# berechne die Anzahl Superhosts im airbnb Datensatz
n_superhosts <- sum(airbnb$Host_superhost)
valueBox()
Funktion und zwar direkt unterhalb des Codes der Aufgabe D2. Gebe dabei als erstes Argument n_superhosts
ein und setze caption
auf "Superhost"
.# Erstelle valueBox
valueBox(XXX, caption = "XXX")
Funktioniert das schon so?
Ein paar Dinge fehlen noch. Zunächst stimmt die Farbe nicht. Füge in die valueBox()
Funktion ein Argument color
ein und setze dieses auf "#6BB7B9"
.
Passt es jetzt?
Bisher ist noch kein Icon vorhanden. Füge in die valueBox()
Funktion ein weiteres Argument icon
ein und setze dieses auf "fa-medal"
.
Fast geschafft; der Titel ist noch etwas zu klein. Um das zu fixen, ersetze "Superhost"
im caption
Argument mit "<h3 style='color: white;'>Superhost</h3>"
. Damit passt nun alles. Um die anderen beiden value Boxen kümmern wir uns später.
So, das war es für den Moment für diese Seite; die interaktiven Grafiken erstellen wir weiter unten. Gehe im Code zur zweiten Seite. Dort wirst du den Text erstellen.
Schaue dir den Text in der rechten Spalte des Dashboards an. Versuche ihn mit deinen bisher erworbenen RMarkdown Kenntnissen selbst nachzubauen.
Du kannst deinen Text mit dem untenstehenden Code, mit dem diese Spalte tatsächlich erstellt wurde, vergleichen. Hast du alles gleich gemacht? Wo hast du andere Lösungen gefunden?
**Airbnbs in Berlin**
Das erste Airbnb in Berlin öffnete 2009 im Stadtteil [Pankow](https://de.wikipedia.org/wiki/Berlin-Pankow) (siehe auch [Übersichtskarte](#page-1)). Von da an war ein rascher Anstieg zu verzeichnen. Bereits 6 Jahre später gab es in Berlin-Pankow alleine `r round(10**2.3)` Airbnbs. Mittlerweile ist diese Zahl auf rund `r round(10**3.2 / 100) * 100` angestiegen.
Das teuerste heute verfügbare Airbnb kostet dabei `r max(airbnb$Preis)` pro Nacht; für die meisten Leute nicht gerade ein Schnäppchen. Dabei handelt es sich um ein `r airbnb$Unterkunftsart[max(airbnb$Preis)]` im Stadtteil `r airbnb$Stadtteil[max(airbnb$Preis)]`.
Insgesamt wurden über die Jahre in Berlin `r as.integer(sum(airbnb$Host_anzahl))` Gäste in Airbnbs empfangen.
Das war es schon für diese Seite. Den Plot erstellen wir wiederum später. Gehe nun in deinem Dokument zur dritten Seite zum Titel Gesamtrating
(Titel dritter Ordnung).
Erstelle unterhalb des Titels einen R chunk und füge den untenstehenden Code ein. Dieser erstellt die erste Grafik.
# Erstelle das Histogramm der Gesamtratings
# Wähle die Rating_gesamt Variable zum Plotten aus
ggplot(airbnb, aes(Rating_gesamt)) +
# Erstelle ein Histogramm mit Balkenbreite 1
geom_histogram(binwidth = 1) +
# Definiere die Achsenbeschriftungen
labs(x = "Gesamtrating",
y = "Häufigkeit") +
# Definiere den Range der x-Achse von 0 bis 100
coord_cartesian(xlim = c(0, 100)) +
# Wähle ein Design für den Plot
theme_light() +
# Vergrössere die Achsenbeschriftungen
theme(
axis.title = element_text(size = 16),
axis.text = element_text(size = 12)
)
INHALT LINKE SPALTE (der eben erstellte Plot)
***
INHALT RECHTE (KOMMENTAR-) SPALTE
Füge nun einen fettgedruckten Titel (mit **TITEL**
) unterhalb der eben eingefügten drei Sterne ein. Wähle als Titel Mittlere Gesamtratings
.
Um den gauge
zu erstellen, berechne zuerst das mittlere Gesamtrating. Erstelle dazu einen neuen Code Chunk und füge den untenstehenden Code ein.
# Berechne mittleres Gesamtrating und Runde auf eine Kommastelle
gesamtrating <- airbnb %>%
pull(Rating_gesamt) %>% mean(na.rm = TRUE) %>% round(1)
gauge
erstellen. Verwende das untenstehende Template und setze das gesamtrating
Objekt als erstes Argument ein.# Estelle den gauge mit dem gesamtrating Objekt
gauge(XXX,
# Setze Minimum und Maximum Werte
min = 0, max = 100,
# Definiere Farbwerte mit gaugeSectors
gaugeSectors(
# Grün, wenn der Wert zwischen 80 und 100 liegt
success = c(80, 100),
# Orange, wenn der Wert zwischen 50 un 79 liegt
warning = c(50, 79),
# Rot, wenn der Wert zwischen 0 und 49 liegt
danger = c(0, 49)
))
Wenn du das Dokument jetzt knittest, siehst du, dass die Dimensionen in der Kommentarspalte noch falsch sind, weil der gauge
noch zu gross ist. Um das zu beheben, kannst du fig.width=3, fig.height=1.5, fig.align="center"
in den Code Chunk Optionen erstellt.
Füge nun unterhalb des Code Chunks, der den gauge
definiert, den folgenden Text ein:
<p style="font-size: 20px;">Die Berliner Airbnbs scheinen allgemein in einem
sehr guten Zustand zu sein. Zumindest lassen die hohen Gesamtratings darauf
schliessen.</p>
leaflet
Nun geht es an die Karte auf Seite 1. Gehe in deinem Skript zur Syntax, welche die Zeile 2 auf der ersten Seite erstellt (die Zeile unterhalb der valueBox
en).
leaflet bietet die Möglichkeit, sehr einfach interaktive Karten zu erstellen. Erstelle einen neuen Code chunk mit dem folgenden Code unterhalb des Karte
Titel:
# Definiere Datensatz
airbnb %>%
# Erstelle Plot
leaflet() %>%
# Setze Anfangskoordinaten und Zoomwert
setView(lng = 13.40439, lat = 52.51128, zoom = 12) %>%
# Zeichne Karte
addTiles()
setView
anpassen. Ersetze nun addTiles()
in deinem Code mit dem untenstehenden Code, um die Airbnbs einzuzeichnen: addTiles() %>%
# Füge Marker hinzu
addCircleMarkers(
lng = ~Längengrad,
lat = ~Breitengrad,
radius = 4,
stroke = FALSE, fillOpacity = 0.5,
color = "#6BB7B9"
)
plotly
Entwicklung der Berliner Airbnbs seit 2009
in der linken Spalte auf der zweiten Seite erstellt:### Entwicklung der Berliner Airbnbs seit 2009
HIER!
### Plot zum Verlauf über die Zeit
# Anzahl Stadtteile
n_stadtteile <- length(unique(airbnb$Stadtteil))
# Definiere n_stadtteile verschiedene Farben aus der viridis palette
farben <- viridis(n_stadtteile)
# Passe den Datensatz an
Verlauf <- airbnb %>%
# Gruppiere über Stadtteile
group_by(Stadtteil) %>%
# Ordne Zeilen Aufsteigend nach Erstellungsdatum
arrange(Erstellungsdatum) %>%
# Erstelle neue Variablen Datum und Kumulativ,
# letztere als 10er Logarithmus der Anzahl Airbnbs
mutate(Datum = Erstellungsdatum,
Kumulativ = log10(1:n())) %>%
# Gruppiere über Stadtteil, Datum, und Kumulativ Variablen
group_by(Stadtteil, Datum, Kumulativ) %>%
# Berechne deskriptive Statistiken und erstelle Variable mit
# Text für Popup Felder
summarise(
m_preis = mean(Preis, na.rm = TRUE),
superhosts = sum(Host_superhost, na.rm = TRUE),
m_rating = mean(Rating_gesamt, na.rm = TRUE),
hover_text = paste0("Mittlerer Preis: <b>", m_preis,
"</b><br>Superhosts: <b>", superhosts,
"</b><br>Mittleres Gesamtrating: <b>",
m_rating, "</b>")
) %>%
# Erstelle den Plot mit Datum auf der x- und Kumulativ auf der y-Achse
# Separate und eingefärbte Linien pro Stadtteil
ggplot(aes(x = Datum, y = Kumulativ, col = Stadtteil)) +
# Zeichne Punkte ein; das text Argument wird später von ggplotly() verwendet
geom_point(aes(text = hover_text)) +
# Zeichne Linien
geom_line(show.legend = FALSE) +
# Definiere Farbwerte; Objekt farben stammt noch von der Karte auf p.1
scale_color_manual(values = farben) +
# Definiere y-Achsenbeschriftung; verwendet HTML wegen plotly
ylab("log<sub>10</sub>(Kumulative Häufigkeit)") +
# Definiere Plot design
theme_light()
# Erstelle Plot
Verlauf
Der Code von Aufgabe F2 erstellt einen statischen Plot. Dieses ggplot
Objekt kann jetzt ganz einfach an ggplotly()
, einer plotly
Funktion weitergegeben werden, um den Plot interaktiv zu gestalten. Dazu musst du nur das Verlauf
am Ende des R chunks in ggplotly(Verlauf)
umwandeln. Fertig!
Bzw. fast fertig. Passe die Dimensionen des Plots (fig.width
und fig.height
in den R Chunk Optionen) so an, dass die Spalte möglichst ausgefüllt wird. Dazu musst du evtl. ein paar Werte ausprobieren …
valueBox
musst du zuerst die Anzahl Airbnbs, welche überall Topratings haben berechnen. Verwende dazu den untenstehenden Code in einem R chunk, diesmal unterhalb des “Allstar” Titels.# Berechne die Anzahl allstars, mit ausschliesslich top ratings
allstar <- airbnb %>%
# Rating_gesamt ist von 0 bis 100 -> reskaliere auf 0 bis 10
mutate(Rating_gesamt = Rating_gesamt / 10) %>%
# Behalte ausschliessliche Spalten mit Ratings
select(starts_with("Rating")) %>%
# Berechne die Mittelwerte jeder Zeile über alle Spalten
mutate(Ratings_m = rowMeans(.)) %>%
# Behalte nur die Zeilen mit Mittelwert 10 (Maximum Rating)
filter(Ratings_m == 10) %>%
# Zähle die Anzahl verbliebener Zeilen
summarise(n())
Verwende den valueBox
Code den du in Teil D erstellt hast als Template um die value Box der Anzahl Allstars zu erstellen. Ersetze dazu n_superhosts
durch allstar
und ändere das "Superhost"
im caption Argument zu "Allstars"
.
Diese value Box sieht aber noch nicht ganz gleich aus wie im vorgegebenen Dashboard. Zum Einen ist die Farbe noch grün statt gold, zum Anderen ist das Icon noch falsch. Ändere zunächst die Farbe (das color
Argument) von "#6BB7B9"
zu "#f5d142"
.
Nun ändere den Input zum icon
Argument von "fa-medal"
zu "fa-gem"
. Dabei spezifiziert das “fa-”, dass das Icon aus der Font Awesome Sammlung stammt. “medal” und “gem” geben dann den Namen des Icons an.
Nun zur dritten value Box, die die Anzahl preiswerter Airbnbs - definiert als weniger als 100 Euro pro Nacht - angibt. Berechne dazu zunächst die Anzahl mit dem untenstehenden Code in einem R chunk unterhalb des “Preiswert” Titels.
# Berechne die Anzahl preiswerter Airbnbs
preiswert <- sum(airbnb$Preis < 100)
Verwende wiederum den valueBox
Code von Aufgaben im Teil D als Template um nun die value Box zu erstellen. Ersetze dazu n_superhosts
durch preiswert
und ersetze das "Superhost"
durch "Preiswert"
. Ändere ausserdem das icon
zu "fa-money-bill-wave"
und die Farbe zu "#85a95d"
.
Auf Seite 3 sind noch zwei Seiten des Storyboards leer. Fülle diese mit Inhalt; du kannst dich dabei and das vorgegebene Dashboard halten (siehe Aufgaben im Abschnitt D für Hilfestellungen), oder eigene Dinge ausprobieren.
Der airbnb.csv Datensatz enthält Zahlen zu 9868 Berliner Airbnbs
Variable | Beschreibung |
---|---|
Preis | Preis pro Nacht |
Erstellungsdatum | Eröffnungsdatum des Airbnbs |
Unterkunftsart | Appartement, Loft, House, etc. |
Schlafplätze | Anzahl Schlafplätze |
Schlafzimmer | Anzahl Schlafzimmer |
Badezimmer | Anzahl Badezimmer |
Reinigungsgebühr | Reinigungsgebühr |
Verfügbarkeit_90Tage | |
Viertel | In welchem Viertel befindet sich das Airbnb |
Stadtteil | In welchem Stadtteil befindet sich das Airbnb |
Breitengrad | Breitengrad |
Längengrad | Längengrad |
Host_id | Host id |
Host_seit | Erfahrung des Hosts |
Host_antwortzeit | Host Antwortzeit |
Host_antwortrate | Host Antwortrate |
Host_superhost | Superhost Ja/Nein |
Host_anzahl | Anzahl Gäste |
Rating_gesamt | Gesamtrating |
Rating_genauigkeit | Genauigkeitsrating |
Rating_sauberkeit | Sauberkeitsrating |
Rating_checkin | Checkinrating |
Rating_kommunikation | Kommunikationsrating |
Rating_lage | Lagerating |
Rating_wertigkeit | Wertigkeitsrating |
Küche | Küche vorhanden TRUE/FALSE |
Wifi | WLAN vorhanden TRUE/FALSE |
TV | TV vorhanden TRUE/FALSE |
Kaffeemaschine | Kaffeemaschine vorhanden TRUE/FALSE |
Geschirrspüler | Geschirrspüler vorhanden TRUE/FALSE |
Terrasse_Balkon | Terrasse/Balkon vorhanden TRUE/FALSE |
Badewanne | Badewanne vorhanden TRUE/FALSE |
Check_in_24h | 24h Check-In vorhanden TRUE/FALSE |
Paket | Installation |
---|---|
tidyverse |
install.packages("tidyverse") |
flexdashboard |
install.packages("flexdashboard") |
plotly |
install.packages("plotly") |
leaflet |
install.packages("leaflet") |
viridis |
install.packages("viridis") |
htmltools |
install.packages("htmltools") |
patchwork |
install.packages("patchwork") |
Funktion | Paket | Beschreibung |
---|---|---|
gauge() |
flexdashboard |
Erstelle einen gauge. |
valueBox() |
flexdashboard |
Erstelle eine value Box |
ggplotly() |
plotly |
Konvertiere ggplot2 Objekt in plotly Objekt |
leaflet() |
leaflet |
Initiiere leaflet Karte |
setView() |
leaflet |
Definiere Anfangsfenster |
addTiles() |
leaflet |
Zeige Karte |
addCircleMarkers() |
leaflet |
Füge Kreisförmige Marker auf die Karte |