Mit dem beim letzten Mal vorgestellten Datensatz wollen wir heute als erstes einmal eine schon immer kontroverse Frage beantworten: Ist Deutschland eine Turniermannschaft?
Wieder benutzen wir R – aus Spaß und weil es erlaubt, solche Analysen relativ kurz zu fassen und auch die Ergebnisse schön zu visualisieren.
Zuerst einmal laden wir den Datenschatz und trennen ihn in einen Qualifikations- und einen Turnierdatensatz.
1data <- read.csv("soccerDataWithFeatures.csv", header = T, na.strings = "-")
2
3qualificationData <- data[grepl("Qualification.*", data$Tournament.Stage), ]
4
5tournamentData <- data[!(grepl("Qualification.*", data$Tournament.Stage) | grepl("Friendly.*",
6 data$Tournament)), ]
7tournamentData <- tournamentData[grepl("Euro.*", tournamentData$Tournament) |
8 grepl("World Cup.*", tournamentData$Tournament), ]
Dann zählen für jede Mannschaft in jedem Datensatz Siege und Niederlagen und räumen ein wenig auf, indem wir alle Mannschaften mit weniger als 3 Spielen rauswerfen.
1teamNames <- unique(append(levels(data$Home.Team), levels(data$Away.Team)))
2
3gamesForTeam <- function(teamName, inData) length(inData[inData$Home.Team ==
4 teamName | inData$Away.Team == teamName, 1])
5
6winsForTeam <- function(teamName, inData) {
7 wins <- length(inData[inData$Class == "HOME_WIN" & inData$Home.Team == teamName,
8 1])
9 wins <- wins + length(inData[inData$Class == "AWAY_WIN" & inData$Away.Team ==
10 teamName, 1])
11 return(wins)
12}
13
14computeTeamResults <- function(teamNames, inData) {
15 gamesPerTeam <- lapply(teamNames, gamesForTeam, inData = inData)
16 winsPerTeam <- lapply(teamNames, winsForTeam, inData = inData)
17 proportionWins <- unlist(winsPerTeam)/unlist(gamesPerTeam)
18 toReturn <- matrix(c(teamNames, gamesPerTeam, winsPerTeam, proportionWins),
19 ncol = 4)
20 toReturn <- toReturn[toReturn[, 2] > 2, ]
21 return(toReturn)
22}
23
24qualificationTeamResults <- computeTeamResults(teamNames, qualificationData)
25tournamentTeamResults <- computeTeamResults(teamNames, tournamentData)
Dann können wir als erstes mal anschauen, wie denn die Verteilung des Anteils der Siege für die Mannschaften aussieht (Deutschland tragen wir als rote Linie ein).
1valueGermanyQualification <- t(qualificationTeamResults[qualificationTeamResults[, 2 1] == "Germany", ])[1, 4] 3valueGermanyTournament <- t(tournamentTeamResults[tournamentTeamResults[, 1] == 4 "Germany", ])[1, 4] 5 6par(mfcol = c(1, 2)) 7hist(unlist(qualificationTeamResults[, 4]), ylim = c(0, 40), xlab = "Anteil Siege", 8 ylab = "Anzahl Mannschaften", main = "Qualifikation", col = "steelblue3", 9 border = "grey20", breaks = c(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 10 0.9, 1)) 11abline(v = valueGermanyQualification, col = "red") 12hist(unlist(tournamentTeamResults[, 4]), ylim = c(0, 20), xlab = "Anteil Siege", 13 ylab = "Anzahl Mannschaften", main = "Turnier", col = "steelblue3", border = "grey20", 14 breaks = c(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1)) 15abline(v = valueGermanyTournament, col = "red")
Womit auch noch einmal gleich optisch deutlich wird, dass die deutsche Mannschaft zu den besten Mannschaften gehört – gemessen am Anteil der gewonnenen Spiele ist sie in Qualifikation und Turnier ganz vorne dabei.
Definition 1: (Vergleichsweise) positive Veränderung des Gewinnanteils
Nun müssen wir aber noch konkret bestimmen, was man denn rechnerisch unter eine Turniermannschaft verstehen möchte. Eine Möglichkeit wäre es, eine Mannschaft als Turniermannschaft zu bezeichnen, wenn bei dieser Mannschaft der Anteil der gewonnenen Spiele im Turnier höher ist als in der Qualifikation (bzw. sich wenigsten weniger stark verringert als bei anderen Mannschaften). Der Code:
1changeWinProportion <- apply(tournamentTeamResults,c(1),function(row) { 2 teamName <- unlist(row[1]) 3 qualificationRowNumber <- which(qualificationTeamResults[,1]==teamName) 4 qualificationRow <- qualificationTeamResults[qualificationRowNumber,] 5 winProportionChange <- unlist(row[4]) - unlist(qualificationRow[4]) 6 return (c(teamName,winProportionChange)) 7 } 8) 9 10changeWinProportion <- t(changeWinProportion[,order(as.numeric(changeWinProportion[2,]),decreasing=TRUE)]) 11 12changeWinProportionDF <- data.frame(changeWinProportion[,1],as.numeric(changeWinProportion[,2]),stringsAsFactors=FALSE) 13names(changeWinProportionDF) <- c("Names","Change") 14 15ggplot(changeWinProportionDF, aes(x=Change, y=reorder(Names, Change))) + 16 geom_point(size=3) + # Use a larger dot 17 theme_bw() + 18 xlab("Change in win proportion") + 19 ylab("") + 20 theme(panel.grid.major.x = element_blank(), 21 panel.grid.minor.x = element_blank(), 22 panel.grid.major.y = element_line(colour="grey60", linetype="dotted"))
Und das Ergebnis:
Position 13 von 46 – na ja, im oberen Mittelfeld.
Nun ist das aber vielleicht auch unfair, weil Mannschaften die nur an wenigen Turnieren teilgenommen haben hier schnell einen höheren Wert haben als die Mannschaften die an vielen Turnieren teilgenommen haben. Um das zu korrigieren können wir auf die absoluten Zahlen schauen; aus dem Anteil der Siege in der Qualifikation bestimmen wir die erwartete Anzahl der Siege im Turnier (ohne Berücksichtigung der Stärke der Mannschaften) und betrachten dann die absolute Abweichung, d.h. die Anzahl der Spiele die mehr oder weniger gewonnen wurden.
Position 33 von 46 – das hätten wir lieber seingelassen. Nach dieser Definition kann man sicher nicht von einer Turniermannschaft sprechen.
Definition 2: Überraschend gute Turnierergebnisse
Eine weitere Möglichkeit, Turniermannschaften zu definieren, wäre von überraschenden Ergebnissen zu sprechen, d.h. eine Turniermannschaft ist eine, die in Turnieren wiederholt die Erwartungen übertrifft. Wenn wir die Wettquoten als die Erwartungen an eine Mannschaft sehen, dann kann man das einfach berechnen: Angenommen, ich habe in jedem Turnierspiel einer Mannschaft je 1€ auf den Sieg dieser Mannschaft gesetzt – was bleibt dann am Ende (und nach Abzug der Einsätze) übrig? Die Mannschaften bei denen diese Summe positiv ist, können wir dann (für den betrachteten Zeitraum) als Turniermannschaften bezeichnen.
Leider liegen uns nicht alle Wettquoten vor (gerade für kleinere Begegnungen wie Saudi Arabien gegen Tunesien finden wir die nicht), aber wir berechnen das trotzdem mal. Erst wieder der Code:
1noOvertime <- function(string) nchar(as(string, "character")) == 0
2
3winningsForTeam <- function(teamName) {
4 winnings <- sum(tournamentData[tournamentData$Class == "HOME_WIN" & tournamentData$Home.Team ==
5 teamName & noOvertime(tournamentData$Extra.Time), 6])
6 winnings <- winnings + sum(tournamentData[tournamentData$Class == "AWAY_WIN" &
7 tournamentData$Away.Team == teamName & noOvertime(tournamentData$Extra.Time),
8 8])
9 return(winnings - gamesForTeam(teamName, tournamentData))
10}
11
12tournamentTeamNames <- sapply(unique(tournamentData$Home.Team), as.character)
13totalWinningsForTeam <- unlist(lapply(X = tournamentTeamNames, FUN = winningsForTeam))
14
15winningsDF <- data.frame(tournamentTeamNames, totalWinningsForTeam, stringsAsFactors = FALSE)
16
17
18ggplot(winningsDF, aes(x = totalWinningsForTeam, y = reorder(tournamentTeamNames,
19 totalWinningsForTeam))) + geom_point(size = 3, aes(color = totalWinningsForTeam)) +
20 scale_colour_gradientn(colours = c("red", "forestgreen"), guide = FALSE) +
21 theme_bw() + xlab("Gesamtgewinn (oder Verlust)") + ylab("") + theme(panel.grid.major.x = element_blank(),
22 panel.grid.minor.x = element_blank(), panel.grid.major.y = element_line(colour = "grey60",
23 linetype = "dotted"))
Und das Ergebnis:
Und zumindest nach dieser Definition können wir sehr deutlich sagen, dass Deutschland in den letzten Jahren eine Turniermannschaft war – nur die Schweiz hat sie da noch übertroffen (wie kann das sein, wo doch die Schweiz in 2008 so entäuscht hat? – in erster Linie wegen dem sehr überraschenden Sieg der Schweizer gegen Spanien bei der WM 2010 (die Wettquote war 14:1) und auch in 2008 hätte man mit dem Setzen auf die Schweiz dank des Sieges gegen Portugal noch einen kleinen Gewinn gemacht – nur bei der WM 2006 hätte man ein paar Cent verloren).
Schluss
Ist Deutschland also eine Turniermanschaft? Am Ende kann man das nicht beantworten, bevor man nicht sehr viel genauer definiert, was eigentlich damit gemeint ist und über welchen Zeitraum man redet. Ich persönlich finde die Definition über die Wettquoten am überzeugendsten und würde deswegen mit “ja” antworten – aber am Ende ist das eine Frage des Anwendungsfalls – oder hier: des persönlichen Geschmacks.
Soviel für heute – beim nächsten Mal geht es dann um die Vorbereitung der Daten für die Vorhersage.
Weitere Artikel der Data Analytics Serie
Teil 1 – Daten sammeln und bereinigen
Teil 2 – Ist Deutschland eine Turniermannschaft?
Teil 3 – Feature Engineering
Teil 4 – Feature Selection
Teil 5 – Logistische Regression und Random Forest
Teil 6 – Die Heimspielproblematik und Vorhersagen für die KO-Runde
Weitere Beiträge
von Valentin Zacharias
Dein Job bei codecentric?
Jobs
Agile Developer und Consultant (w/d/m)
Alle Standorte
Gemeinsam bessere Projekte umsetzen.
Wir helfen deinem Unternehmen.
Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.
Hilf uns, noch besser zu werden.
Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.
Blog-Autor*in
Valentin Zacharias
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.