Daten analysieren: Die ersten Schritte. Tutorial Teil II

Wie umfangreich die Daten über die NFL tatsächlich sind, wie ihr euch ihnen annähern könnt und wieso das auch alles sinnvoll ist: Teil 2 des R-Tutorials.

3
360
5
(8)
Lesezeit: 5 Minuten

Wiederholung vom letzten Mal

Nachdem ich euch im letzten Tutorial grob erklärt habe, wie sich die Oberfläche von RStudio zusammen setzt und wie ihr die Daten auf eurer Festplatte speichert, will ich heute zeigen, wie man Daten auswählt und zusammenfasst. Auf einen theoretischen Exkurs verzichte ich erst einmal. Es soll schlicht um das “Daten analysieren” gehen.

Bei jeder Sitzung, die ihr in RStudio beginnt, müsst ihr die “packages”, die ihr in jener nutzen wollt, erneut abrufen. Heißt, dass ihr die installierten packages bei jedem Neustart mittels der library() Funktion abrufen müsst. Es gibt einige Standard packages, die ihr jedes Mal, wenn ihr mit den NFL-Daten arbeitet, abrufen werdet. Es bietet sich an, diese in einem Extra-Skript gespeichert zu haben und dann per se erst einmal nach dem Start abzurufen. Wir rufen zunächst jene ab, die im letzten Tutorial benutzt wurden:

library(devtools)
library(dplyr)
library(dbplyr)
library(nflfastR)
library(DBI) 
library(RSQLite)

Eure Daten bringt ihr mit

update_db()

auf den neusten Stand. Mittels

connection <- dbConnect(SQLite(), "./pbp_db")
connection
pbp_db <- tbl(connection, "nflfastR_pbp")

verbindet ihr euch mit eurer auf der Festplatte gespeicherten Datenbank.

Dieses Mal soll es vor allem um die grundlegenden Operatoren gehen, mittels derer ihr Fälle oder Variablen auswählt und wie ihr die über Spiele oder Jahre hinweg zusammenfassen und analysieren könnt.

Die Datenbank, die ihr nach im letzten Tutorial heruntergeladen habt, umfasst knapp eine Millionen Reihen (Spielzüge) mit jeweils 328 Variablen. Das ist ein riesiger Datensatz, dem man sich nur Stück für Stück annähern kann. Und auch sollte.

Daten auswählen

Möchten wir uns beispielsweise – darum wird es in meinem Beispiel heute und beim nächsten Mal gehen – anschauen, wie Colin Kaepernick in seiner Karriere als Passer abgeschnitten hat, wählen wir nur die Snaps aus, in denen er tatsächlich geworfen hat. Dafür benutzt ihr zunächst die Funktion filter().

Wir kreieren ein neues Objekt, dem wir Informationen. Wir nennen diesen Kaep_pass:

Kaep_pass <- pbp_db %>% filter(passer == "C.Kaepernick")

Die Operatoren <- und %>% sind fundamental. Mit Ersterem weist ihr einer bestimmten Variable Informationen zu. Der Zweite verbindet verschiedene Befehle miteinander. Im “Tidyverse” nennt man das auch “pipe” (nützlicher Shortcut dafür: Strg+Shift+m). Am Beispiel Kaep_pass werden hier alle Reihen zugewiesen, die in den Daten von pbp_db (also der nflfastR-Datenbank auf eurer Festplatte) enthalten sind UND bei denen der passer “C.Kaepernick“ heißt.

Setzt ihr hinter die Zeile noch

%>% collect() 

könnt ihr diese Fälle abrufen, was dauert und wenig ertragreich ist. So sähe das etwa aus.

Screenshot 1. Datenausschnitt aller verfügbaren Daten zu jedem Snap von C. Kaepernick als passer

Wir möchten aber nicht jede Information über jeden Snap mit Kaepernick analysieren – das wären 2347 insgesamt, jeweils auf 328 Variablen – sondern wollen uns anschauen, wie er sich in der NFL als Passer geschlagen hat. Dazu brauchen wir nicht betrachten, wer der Gegner war, wieviele Timeouts das Heimteam hatte oder wie das Wetter war. All diese Informationen könnten wir ausblenden. Wollen wir aber gerade nicht.

Jetzt kommt die select() Funktion zum Tragen. Ich wähle hier die Variablen (Spalten) aus, die viel über einen Quarterback aussagen: epa, cpoe, wpa, success, air_epa und yards_gained. Was diese Metriken genau aussagen, könnt ihr in unserem in Lexikon nachlesen. Wir aktualisieren also Kaep_pass, indem wir aus dem ursprünglichen Datensatz diese Variablen auswählen. Damit die Information darüber, wer den Ball wann geworfen hat, nicht verloren geht, wählen wir noch passer und season aus. Der Code sieht dann so aus

Kaep_pass <- Kaep_pass %>% select(epa, cpoe, wpa, success, air_epa, yards_gained, passer, season) 

Weiterhin umfasst dieses neue Objekt 2347 Zeilen, heißt aufgezeichnete Plays (das seht ihr in „Environment“ angezeigt). Doch statt 328 Spalten, bleiben pro Zeile nur noch 8 übrig.

Daten bündeln, um sie zu analysieren

Jetzt nähern wir uns langsam dem, was ich hier und im nächsten Tutorial untersuchen werde: Ich möchte deskriptiv betrachten, inwiefern Kaepernicks Leistungen in seinen Jahren als Starter denen der Backups in den Jahren nach seiner Demission ähneln. Also ob der 2016er Kaep wirklich so schlecht war, dass eine Verpflichtung als Backup aus analytischer Sicht abwegig gewesen wäre. Dafür mitteln wir seine Leistungen jede Saison über die vorher ausgewählten Indizes (epa, cpoe etc.). Dafür braucht es zwei Befehle, die ihr immer wieder nutzen werdet: group_by() und summarise().

group_by() bündelt dabei, wie der Name sagt, um eine bestimmte Variable alle Fälle. Wir möchten uns Kaepernicks Leistung pro Saison analysieren, also gruppieren wir alle oben genannten Variablen um die Variable season.

Kaep_pass <- Kaep_pass %>% group_by(season)

Jetzt fassen wir jede der ausgewählten Variablen je Saison zusammen (für die Übersichtlichkeit nennen wir dieses neue Objekt Kaep_pass_year):

Kaep_pass_year <- Kaep_pass %>% summarise(passer, epa = mean(epa, na.rm = TRUE), cpoe = mean(cpoe, na.rm = TRUE), wpa = mean(wpa, na.rm = TRUE), success = mean(success, na.rm = TRUE), air_epa = mean(air_epa, na.rm = TRUE), tot_yds = sum(yards_gained), plays = n()) %>% collect()

Das sieht komplizierter aus, als es ist. summarise() ermöglicht es, verschiedene Werte zu berechnen, bei Angabe immer auf gruppierte Variablen wie season oder passer. Wir haben vor allem mean, also den Mittelwert einer Variable über eine Saison berechnen lassen. Der Zusatz „na.rm = TRUE“ in der Klammer legt fest, dass fehlende Werte dabei ausgeschlossen werden. Würden wir das nicht festlegen, würde der Mittelwert bei einem einzigen fehlenden Wert bei irgend einem Snap in einer Saison nicht ermittelt werden können. summarise() kennt noch diverse andere Möglichkeiten, Werte zusammen zu fassen, wie etwa im obigen Beispiel sum(). Dieser ergibt hier die Summe aller Yards in einer Saison, die Kaepernick geworfen hat.

Abschluss und Ausblick auf das nächste Tutorial

Schauen wir uns mal die Daten an:

print(Kaep_pass_year)
Screenshot 2: advanced stats von Colin Kaepernick als passer

In dieser Tabelle sind die Mittelwerte für EPA, CPOE, WPA, Success, Air_Epa, als auch die insgesamt geworfenen Yards und die Anzahl der Würfe pro Saison dargestellt.

Letzteres ist enorm wichtig: Über das Problem der sample size müssen wir im nächsten Tutorial sprechen, aber ihr könnt euch bereits ausmalen, dass 5 Pässe, die Kaepernick 2011 geworfen hat, wenig über seine tatsächliche Leistungsfähigkeit aussagen. Wie wir uns diesem Problem annehmen und ob Kaepernick zurecht, auf Grund seiner Leistungen, keinen Vertrag mehr bekam, dazu kommen wir beim nächsten Mal.

3 KOMMENTARE

  1. Der Code ist komplett da eigentlich. Also nichts, was gezeigt wird, wird nicht in Code ausgedrückt. Kannst du sagen, was dir fehlt?

  2. Super, dass ihr eine Gelegenheit schafft sich auch mit dem Thema zu beschäftigen.
    Mir würde es allerdings helfen, wenn ihr ab und zu den kompletten Code zeigt und nicht nur die Schnipsel welche dann selber zugeordnet werden müssen.

  3. kurze Frage: Damit man den Datensatz so wie in deinem ersten Screenshot sieht, muss man da wirklich den Befehl collect () eingeben oder print () ?

Schreibe eine Antwort

Scheibe deinen Kommentar
Sag uns deinen Namen