Читать книгу R für Data Science - Hadley Wickham - Страница 67
Zähler
ОглавлениеWenn Sie Daten aggregieren, empfiehlt es sich immer, entweder einen Zähler (n()) oder einen Zähler von nicht fehlenden Werten (sum(!is.na(x))) einzubinden. Auf diese Weise können Sie sicherstellen, dass Sie keine Schlussfolgerungen aus sehr geringen Datenmengen ziehen. Sehen wir uns beispielsweise die Flüge (anhand des Luftfahrzeugkennzeichens, tailnum) an, die die höchsten durchschnittlichen Verspätungen haben:
delays <- not_cancelled %>%
group_by(tailnum) %>%
summarize(
delay = mean(arr_delay)
)
ggplot(data = delays, mapping = aes(x = delay)) +
geom_freqpoly(binwidth = 10)
Oha! Es gibt einige Flugzeuge, die eine durchschnittliche Verspätung von fünf Stunden (300 Minuten) haben!
Die Geschichte ist eigentlich etwas differenzierter zu betrachten. Wir bekommen einen besseren Einblick, wenn wir ein Streudiagramm mit der Anzahl der Flüge über der durchschnittlichen Verspätung zeichnen:
delays <- not_cancelled %>%
group_by(tailnum) %>%
summarize(
delay = mean(arr_delay, na.rm = TRUE),
n = n()
)
ggplot(data = delays, mapping = aes(x = n, y = delay)) +
geom_point(alpha = 1/10)
Es dürfte nicht überraschen, dass die Variation der durchschnittlichen Verspätung wesentlich größer ist, wenn weniger Flüge in die Auswertung eingehen. Die Form dieses Diagramms ist charakteristisch: Wenn man einen Mittelwert (oder eine andere Zusammenfassung) über der Gruppengröße aufträgt, sieht man, dass die Variation abnimmt, wenn die Größe der Stichprobe zunimmt.
Bei derartigen Diagrammen ist es oftmals zweckmäßig, die Gruppen mit den wenigsten Beobachtungen auszufiltern, um das Muster hervortreten zu lassen und nicht die extreme Variation in den kleinsten Gruppen. Genau das geschieht beim folgenden Code. Zudem zeigt er ein praktisches Schema, um ggplot2 in dplyr-Abläufe zu integrieren. Es ist zwar schade, dass Sie von %>% zu + wechseln müssen, doch sobald Sie den Dreh raushaben, ist es ziemlich komfortabel:
delays %>%
filter(n > 25) %>%
ggplot(mapping = aes(x = n, y = delay)) +
geom_point(alpha = 1/10)
Eine nützliche Tastenkombination ist MacBefehl/Strg + Umschalt + P. Damit wird der zuvor gesendete Block vom Editor an die Konsole gesendet. Das ist insbesondere dann komfortabel, wenn Sie etwa den Wert von n im vorherigen Beispiel untersuchen. Sie senden den gesamten Block einmal mit MacBefehl/Strg+Eingabe, modifizieren dann den Wert von n und drücken MacBefehl/Strg + Umschalt + P, um den vollständigen Block erneut zu senden. |
Für diesen Mustertyp gibt es noch eine andere häufige Variation. Sehen wir uns an, wie die durchschnittliche Leistung des Schlagmanns im Baseball in Beziehung zur Anzahl der Schlagversuche (At-Bats) steht. Ich verwende hier die Daten aus dem Paket Lahman, um den Schlagdurchschnitt (Anzahl der geglückten Schläge / Anzahl der Schlagversuche) jedes Hauptakteurs beim Baseball zu berechnen.
Wenn ich die Geschicklichkeit des Schlagmanns (gemessen am Schlagdurchschnitt, ba) über der Anzahl der Möglichkeiten, den Ball zu treffen (gemessen nach Schlagversuchen, ab) auftrage, lassen sich zwei Muster erkennen:
Wie oben gezeigt, wird die Varianz kleiner, wenn mehr Datenpunkte vorhanden sind.
Es gibt eine positive Korrelation zwischen Geschicklichkeit (ba) und den Gelegenheiten, den Ball zu treffen (ab). Denn die Teams kontrollieren, wer das Spiel bekommt, und zweifellos wählen sie ihre besten Spieler aus:
# Convert to a tibble so it prints nicely
batting <- as_tibble(Lahman::Batting)
batters <- batting %>%
group_by(playerID) %>%
summarize(
ba = sum(H, na.rm = TRUE) / sum(AB, na.rm = TRUE),
ab = sum(AB, na.rm = TRUE)
)
batters %>%
filter(ab > 100) %>%
ggplot(mapping = aes(x = ab, y = ba)) +
geom_point() +
geom_smooth(se = FALSE)
#> `geom_smooth()` using method = 'gam'
Dies hat auch erhebliche Auswirkungen auf das Ranking. Wenn Sie unbefangen nach desc(ba) sortieren, sind die Leute mit den besten durchschnittlichen Schlagzahlen zweifellos glücklich, aber nicht zwangsläufig die Geschicktesten:
batters %>%
arrange(desc(ba))
#> # A tibble: 18,659 × 3
#> playerID ba ab
#> <chr> <dbl> <int>
#> 1 abramge01 1 1
#> 2 banisje01 1 1
#> 3 bartocl01 1 1
#> 4 bassdo01 1 1
#> 5 birasst01 1 2
#> 6 bruneju01 1 1
#> # ... with 1.865e+04 more rows
Eine gute Erklärung für dieses Problem finden Sie zum Beispiel unter http://bit.ly/Bayesbbal und http://bit.ly/notsortavg.