--- title: "Data Science Tutorial" output: learnr::tutorial runtime: shiny_prerendered --- ```{r setup, include=FALSE} library(learnr) library(readxl) library("ggplot2") options(scipen = 10) gameData <- read_excel("bgg_dataset.xlsx", sheet = "Sheet") knitr::opts_chunk$set(echo = FALSE) ``` ## Datenbasis ### Datenherkunft In diesem Praktikum verwenden wir das Dataset "Board Games Analysis 🎲🎲🎯". Die Daten wurden ursprünglich aus der BoardGameGeek-Datenbank extrahiert und anschließend auf Kaggle hochgeladen, wo sie zu einem Datensatz zusammengeführt wurden. Link zum Notebook auf Kaggle: https://www.kaggle.com/code/karnikakapoor/board-games-analysis \ Link zum Datensatz auf Kaggle: https://www.kaggle.com/code/karnikakapoor/board-games-analysis/input ### Inhalt Der Originale Datensatz umfasst 20.343 Einträge und enthält verschiedene Informationen zu Brettspielen. Allerdings wurde der Datensatz für diese Übung auf 500 Einträge gekürzt. Hier sind die Spalten und ihre jeweiligen Inhalte: **ID**: Eine eindeutige Identifikationsnummer für jedes Brettspiel im Datensatz.*(Integer)*\ **Name:** Der Name des Brettspiels.*(String)*\ **Year:** Das Jahr, in dem das Brettspiel veröffentlicht wurde.*(Integer)*\ **Published:** Informationen über die Veröffentlichung des Spiels.*(Integer)*\ **Min Players:** Die minimale Anzahl von Spielern, die das Spiel spielen können.*(Integer)*\ **Max Players:** Die maximale Anzahl von Spielern, die das Spiel unterstützt.*(Integer)*\ **Play Time:** Die durchschnittliche Spielzeit des Brettspiels.*(Integer)*\ **Min Age:** Die empfohlene minimale Altersgruppe für Spieler des Spiels.*(Integer)*\ **Users Rated:** Die Anzahl der Benutzer, die das Spiel bewertet haben.*(Double)*\ **Rating Average:** Der durchschnittliche Bewertungswert des Spiels durch Benutzer.*(Double)*\ **BGG Rank:** Die Rangposition des Spiels auf BoardGameGeek.*(Integer)*\ **Complexity Average:** Der durchschnittliche Schwierigkeitsgrad des Spiels.*(Double)*\ **Owned Users:** Die Anzahl der Benutzer, die das Spiel besitzen.*(Integer)*\ **Mechanics:** Informationen über die Spielmechanismen, die im Brettspiel verwendet werden.*(String)*\ **Domains:** Die Domänen oder Kategorien, zu denen das Brettspiel gehört.*(String)*\ Diese Spalten bieten eine breite Palette von Informationen über die charakteristischen Merkmale, Bewertungen und Eigenschaften der aufgeführten Brettspiele im Datensatz. Die Daten können für Analysen und Erkenntnisse im Bereich der Brettspielindustrie sowie für die Beurteilung von Präferenzen und Trends unter den Spielern verwendet werden. ### Hypothesen Wir haben zwei Hypothesen formuliert, die wir im "Datenanalyse"-Abschnitt testen werden. **Hypothese 1:** Die durchschnittliche Spielzeit betraegt 30 minuten. **Hypothese 2:** Pro Spiel haben 15000 leute eine Bewertung gegeben. ## Datenaufbereitung ### Einlesen von Daten Um Datensätze mit R zu analysieren, müssen diese zuerst eingelesen werden. Je nach Struktur des Datenfiles kommen verschiedene Einlese-Befehle zur Anwendung. Es können u.a. Textfiles (.txt, .dat), Datenfiles (.csv) und Excel-Files eingelesen werden. #### XLSX-Dateien in R importieren In diesem Tutorial benutzen wir eine .xlsx Datei, die wir einlesen müssen. XLSX-Dateien lassen sich aus Excel heraus speichern und sind heutzutage weit verbreitet. Für diese Aufgabe bietet sich das readxl-Paket an, das am einfachsten mit den folgenden Befehlen installiert und geladen wird: ```{r install-readxl, exercise=TRUE} install.packages("readxl") library (readxl) ``` Das Package ist schonmal installiert und wird verwendet, deswegen lässt R nicht zu, dass es wieder installiert wird. Jetzt können wir unseren Datensatz einlesen: ```{r read-data, exercise=TRUE} gameData <- read_excel("bgg_dataset.xlsx", sheet = "Sheet") ``` Aufgrund des Arbeitsverzeichnis funktioniert leider diese Funktion in diesem Dokument nicht, aber keine Sorge, wir haben sie im Hintergrund genauso wie hier benutzt. Wir können jetzt unsere Daten benutzen: ```{r show-data, exercise=TRUE} gameData ``` Wir werden aber häufig nicht mit dem gesamten Datensatz arbeiten, sondern nur mit einigen Spalten. Nur eine Spalte aus dem Datensatz lässt sich wie folgt lesen: ```{r read-column, exercise=TRUE} gameData$`Year Published` ``` #### Zeit zum üben! Schreiben Sie den Code, um die Spalte `Mechanics` zu lesen: ```{r read-mechanics-column, exercise=TRUE} ``` ```{r read-mechanics-column-hint} gameData$Mechanics ``` *Wie Sie weitere Dateientypen einlesen und benutzen können, finden Sie in diesem [Tutorial von Björn Walther](https://bjoernwalther.com/daten-in-r-importieren/)* ### Leerstellen beheben Das Beheben von Leerstellen in R Studio erfordert spezifische Schritte, die je nach Art der Daten und der Art der Probleme variieren können. #### In einer bestimmten Spalte: ```{r remove-empties-column, exercise=TRUE} gameData$`Year Published` <- trimws(gameData$`Year Published`) gameData$`Year Published` ``` #### In allen Spalten: ```{r remove-empties, exercise=TRUE} gameData <- lapply(gameData, trimws) gameData ``` In unserem Dataset scheint alles gut zu sein, deswegen haben wir keine Änderungen nach Ausführung den Befehlen. ### Inkonsistenzen beheben In einem Datensatz beziehen sich Inkonsistenzen auf Unstimmigkeiten, Widersprüche oder Fehler, die in den Daten vorhanden sind und möglicherweise die Qualität der Daten beeinträchtigen. Die unterstehende Befehle helfen uns, diese zu Inkonsistenzen zu beheben. #### Standardisierung der Schreibweise: ```{r to-lowercase-column, exercise=TRUE} gameData$`Mechanics` <- tolower(gameData$`Mechanics`) gameData$`Mechanics` ``` Somit wurden alle Zeichenketten in der Spalte "Mechanics" in Kleinbuchstaben umgewandelt. #### Ersetzen von Werten: ```{r replace-variable, exercise=TRUE} gameData$`Mechanics` <- gsub("Action", "!!!ACTION!!!", gameData$`Mechanics`) gameData$`Mechanics` ``` Somit haben wir alle treffer für "Action" mit "!!!ACTION!!!" ersetzt. #### Behandlung von fehlenden Werten: ```{r replace-missing-variable, exercise=TRUE} gameData$`Rating Average`[is.na(gameData$`Rating Average`)] <- mean(gameData$`Rating Average`, na.rm = TRUE) ``` Dieser Befehl ersetzt fehlende Werte durch der Median der vorhandenen Werten in der Spalte. Was der Median ist, finden Sie in dem nächsten Abschnitt über Datenanalyse. #### Entfernen von Duplikaten Dieser Befehl entfernt Duplikate basierend auf alle Spalten. Wir haben aber in unserem Datensatz keine Duplikate. \ Zum Veranschaulichen benutzen wir ein Vector. ```{r remove-duplicates, exercise=TRUE} vector <- c(1, 2, 3, 3, 5, 2, 1, 7, 10, 5) vector <- unique(vector) vector ``` #### Behandlung von Sonderzeichen ```{r replace-special-chars, exercise=TRUE} gameData$`Mechanics` <- gsub("[^a-zA-Z0-9 ]", "", gameData$`Mechanics`) gameData$`Mechanics` ``` Dieser Befehl entfernt Sonderzeichen in der Spalte "Mechanics". In diesem Fall sind Characters, die nicht ein Buchstabe oder Ziffer sind, entfernt worden (auch die Kommas). #### Notice Diese Beispiele sind allgemeiner Natur, und Sie sollten sie an Ihre spezifischen Daten und Probleme anpassen. Inkonsistenzen und Leerstellen können in verschiedenen Formen auftreten, und es ist wichtig, die geeigneten Methoden für Ihre speziellen Daten anzuwenden. Beachten Sie auch, dass Datenbereinigung oft datenabhängig ist, und eine gründliche Analyse der Daten ist vor der Bereinigung ratsam. ### Jetzt sind Sie dran! Testen Sie, was Sie in diesem Abschnitt über Daten einlesen, gelernt haben: ```{r second-quiz} quiz( question("Mit welchem R-Befehl lassen sich Packages installieren?", answer("install.packages()", correct = TRUE), answer("add.packages()"), answer("install.library()"), answer("install()") ), question("Mit welchem R-Befehl lassen sich die installierten Packages initialisieren?", answer("use()"), answer("library()", correct = TRUE), answer("init()"), answer("install.packages()") ), question("Welcher Packet benutzen wir, um XLSX-Dateien zu lesen?", answer("readxl", correct = TRUE), answer("readxls"), answer("readexcel"), answer("excelread") ), question("Wie lassen sich einzelne Spalten aus dem Datensatz auslesen?", answer("dataset&\\`column\\`"), answer("column$dataset"), answer("dataset%\\`column\\`"), answer("dataset$\\`column\\`", correct = TRUE) ) ) ``` ## Datenanalyse In diesem Teil wird beschrieben, wie man verschiedene Daten mit Funktionen ermitteln kann.\ Hierfür sollte man sich die Daten erneut anschauen.\ Für diesen Teil ist es wichtig zu wissen, wie man auf eine Spalte zugreifen kann. Dies macht man in dem man die Variable in dem der Datensatz gespeichert ist (hier gameData) angibt und den Spaltennamen in entweder zwei eckigen Klammern oder hinter einem $ Zeichen definiert.\ Die Syntax wäre dann beispielsweise:\ ```data[["column"]])``` oder ```data$column```, bzw. ```data$"spaced column name"```\ \ Die Tabelle unten zeigt alle Daten aus dem Datensatz. Mit den Pfeilen in der oberen Reihe kann man die durch die Spalten schalten. ```{r dataset-tale} head(gameData) ``` \ ### Mittelwert Der Mittelwert bestimmt den Durchschnitt aller gegebenen Werte. Die Rechnung dafür ist:\ $(x_{1} + x_{2} + \cdots + x_{n}) / x$\ \ Um den Mittelwert einer Spalte zu bestimmen, vewendet man die 'mean()' Funktion verwenden. In diese setzt man die Variable in der die Daten gespeichert sind (gameData) und gibt die gewünschte Spalte an.\ \ Bestimmen Sie den Mittelwert von "Play Time". ```{r mean, exercise=TRUE} ``` Sie sollten hier den Wert 99.884 bekommen. \ ### Median Der Median ist der Mittelpunkt aller gegebenen Werte.\ \ Der Median wird durch die 'median()' Funktion bestimmt.\ Da das schreiben von ```gameData[["Play Time"]]``` etwas dauert, kann man ab hier die Variable 'ptime' verwenden.\ Bestimmen Sie den Median von "Play Time". ```{r median, exercise=TRUE} ptime <- gameData[["Play Time"]] ``` Sie sollten hier den Wert 90 bekommen. \ ### Varianz Die Varianz bestimmt die Verteilung um den Mittelwert.\ \ Die Varianz wird durch die 'var()' Funktion bestimmt.\ Bestimmen sie die Varianz von "Play Time". ```{r variance, exercise=TRUE} ptime <- gameData$"Play Time" ``` Sie sollten hier den Wert 6070.055 bekommen. \ ### Standardabweichung Die Standardabweichung bestimmt die Wurzel Verteilung um den Mittelwert.\ \ Die Varianz wird durch die 'sd()' Funktion bestimmt.\ Bestimmen sie die Standardabweichung von "Play Time". ```{r standard-deviation, exercise=TRUE} ptime <- gameData$"Play Time" ``` Sie sollten hier den Wert 77.91056 bekommen. \ ### Lineare Regression Die Lineare Regression bestimmt das Verhältnis zwischen zwei Werten(-sets).\ \ Die Varianz wird durch die 'lm()' Funktion bestimmt Hier übergibt man Daten welche mit einem Tilde-Symbol (~) verbunden sind, also beispielsweise ```lm(x~y)```.\ Bestimmen sie die Lineare Regression mit "Users Rated" im Verhältnis zu "Owned Users". ```{r linear-regression, exercise=TRUE} raters <- gameData$"Users Rated" owned <- gameData$"Owned Users" ``` Falls man etwas mehr information will, kann man die Eingabe (oder die Variale in welche man dies gespeichert hat) noch in die ```summary()``` Funktion schreiben.\ Weiterhin kann man dies auf ein Plot abbilden. Dazu verwendet man die ```plot()``` Funktion in welche man einen x und y Wert eingibt, zusammen mit Optionen wie das Plot aussehen soll. Mehr information dazu findet man [in der Dokumentation](https://www.rdocumentation.org/packages/graphics/versions/3.6.2/topics/plot).\ Mit ```abline()``` kann man die Regressionslinie der lm Funktion abbilden. Dazu wird die lm Funktion, oder die Variable in der diese gespeichert ist, an ```abline()``` übergeben.\ ```{r lm-plot-example} raters <- gameData$"Users Rated" owned <- gameData$"Owned Users" x = lm(raters~owned, data = gameData) plot(raters, owned, pch = 16, col = "blue") abline(x) ``` Versuchen Sie nun den oben gezeigten Plot selbst zu erstellen. Die Farbe und Parameter sind bereits vorgegeben. ```{r lm-plot, exercise=TRUE, exercise.lines=5} raters <- gameData$"Users Rated" owned <- gameData$"Owned Users" cavg <- gameData$"Complexity Average" x = lm() plot(, , pch = 16, col = "blue") ``` \ ### Hypothesentest R hat Funktionen zum Testen von Hypothesen. Hier kann man nun den [T-Test](https://www.rdocumentation.org/packages/stats/versions/3.6.2/topics/t.test) anwenden. In der Funktion ```t.test()``` werden die beiden Wertesets eingegeben. Der ausgegebene p-Wert (p-value) kann dann mit dem Signifikanzwert (typischerweise 5%(0.05)) verglichen werden. Ist der Wert groesser als 0.05 kann man annehmen, dass die Null-Hypothese stimmt.\ Die Alternative Hypothese, oder das, was man eigentlich beweisen will, wird ebenfalls im Bericht gezeigt. Einen Testdurchschnitt kann man mit dem Parameter ```mu={value}``` angeben. ```{r hypothesis-test, exercise=TRUE, exercise.lines=4} ptime <- gameData$"Play Time" rated <- gameData$"Users Rated" ``` ```{r hypothesis-quiz} quiz( question("Die durchschnittliche Spielzeit betraegt 30 minuten.", answer("Wahr"), answer("Falsch", correct = TRUE) ), question("Pro Spiel haben 15000 leute eine Bewertung gegeben.", answer("Wahr", correct = TRUE), answer("Falsch") ) ) ``` ## Ergebnispräsentation In diesem Kapitel beschäftigen wir uns mit ausgewählten grafischen Darstellungsmöglichkeiten von Daten und wie man diese in RStudio erstellen kann. ### Streudiagramm Ein Steudiagramm wird häufig verwendet, um einen Zusammenhang zwischen Variablen darzustellen. In RStudio kann man mit Hilfe des plot()-Befehls ein solches Streudiagramm erzeugen. Hier ein Beispiel: ```{r plot} plot(gameData[["Year Published"]],gameData[["ID"]],ylab="ID des Spiels", xlab="Veröffentlichung des Spiels", main="Zusammenhang ID und Erstveröffentlichung eines Spiels",xlim=c(1960,2024)) ``` \ Der Code für dieses Streudiagramms ist grob zusammengefasst: \ \ **plot(gameData[["xxx"]],gameData[["yyy"]],xlim=c(a,z))** \ \ Enthalten sind hier drei Parameter, die beiden Variablen und eine Begrenzung. Wobei xlim eine Begrenzung der x-Achse, und damit die Begrenzung der Werte von "xxx" darstellt, um ein genaueres Bild zu erhalten. \ \ \ \ Erstellen Sie nun anhand des Beispiels ein einfaches Streudiagramm welches den Zusammenhang zwischen "Min Age" und "Complexity Average" darstellt: ```{r plotExercise, exercise=TRUE} ``` ```{r plotExercise-hint} plot(gameData[["Complexity Average"]],gameData[["Min Age"]]) ``` \ \ ### Boxplot-Diagramm Ein Boxplot ist ein Diagramm, dass verschiedene Lageparameter und Streuparameter abbildet und damit einen ersten groben Überblick über eine Verteilung gibt. Meistens verwendet man einen Boxplot um schnell eine Übersicht über Median, Quartile, Minimal- und Maximalwerte sowie Ausreißer zu erhalten. \ Folgend ein Beispiel: ```{r ggplot} ggplot(gameData, aes(y = .data[["Play Time"]], group = .data[["Year Published"]], x = .data[["Year Published"]])) + geom_boxplot() + coord_cartesian(xlim = c(2000, 2020)) ``` \ \ Anhand des Beispiels nun ein kleines Quiz zur Verdeutlichung der Begrifflichkeiten: \ ```{r quiz-ggplot} quiz( question("Was ist der Median im Diagramm?", answer("ein vertikaler Strich"), answer("die Höhe der Box"), answer("ein horizontaler Strich in der Mitter der Box", correct = TRUE), answer("das untere Ende der Box")), question("Was sind die Quartile im Diagramm?(Es sind mehrere Antworten möglich)", answer("das obere Ende der Box", correct = TRUE), answer("Punkte oberhalb der Box"), answer("ein Drittel des vertikalen Strichs"), answer("das untere Ende der Box", correct = TRUE)), question("Was sind die Maximalwerte im Diagramm?", answer("Punkte oberhalb der Box"), answer("die Spitzen des vertikalen Strichs", correct = TRUE), answer("die x-Achse und die y-Achse"), answer("die Flaeche der Box") ), question("An was erkennt man im Diagramm die Ausreißer?", answer("es sind Punkte außerhalb der Box", correct = TRUE), answer("an der Größe der Box"), answer("durch schlechtes Verhalten") ) ) ``` \ \ Um ein Boxplot-Diagramm zu erstellen, muss man das ggplot2-package installiert haben, der grobe Syntax fürs Diagramm selbst sieht wiefolgt aus: \ **ggplot(gameData, aes(y = .data[["xxx"]], group = .data[["yyy"]], x = .data[["yyy"]])) + geom_boxplot()** \ \ \ \ ### Säulendiagramme Das bekannte Säulendiagramm wird meistens verwendet um eine Veränderung im Laufe der Zeit zu zeigen. Mit Säulendiagrammen kann man Steigerung, Rückgang, Stagnation als auch eine Häufigkeitsverteilung deutlich zeigen. Um ein Säulendiagramm in R mit Häufigkeitsverteilung zu erhalten, gibt man den Befehl: \ \ **barplot(table(gameData[["xxx"]])** ein und kann um die Achsen näher zu beschreiben noch **xlab=""** und **ylab=""** einfügen. \ \ Folgend ein Beispiel für ein Säulendiagramm mit Häufigkeitsverteilung: \ ```{r barplot} barplot(table(gameData[["Min Age"]]), xlab = "Altersfreigabe" , ylab = "Häufigkeit", main = "Häufigkeit der Altersfreigaben" ) ``` \ \ Geben Sie nun ein Säulendiagramm mit den Werten von "Complexity Average" und Achsenbeschriftung aus: \ ```{r barplotExercise, exercise=TRUE} ``` ```{r barplotExercise-hint} barplot(gameData[["Complexity Average"]], xlab = "Spiel" , ylab = "Score") ``` \ \ ***Weitere gute Tutorials zu Diagrammen in RStudio findet man bei Björn Walther: https://bjoernwalther.com/tutorials-fuer-r/ *** ## Über uns ### Lino Cortese Lino ist verantwortlich für die Ausarbeitung des Datenanalyse-Abschnitts. ### Maximilian Fronmüller Maxi hat sich auf die Erstellung des Ergebnispräsentation-Abschnitts konzentriert. ### Nikolay Nikolaev Nikolay hat an die Abschnitte Datenbasis und Datenaufbereitung gearbeitet.