Die Altersstruktur des SC Rheindorf Altach

Die Altersstruktur des SC Rheindorf Altach

Ich habe die Altersstruktur des Kaders vom SC Rheindorf Altach grafisch aufbereitet. Das Alter wird in dieser Grafik mit dem Anteil an Einsatzminuten gegenübergestellt. Philipp Netzer ist der älteste Spieler im Kader, seine Einsatzzeit war wegen einer Verletzung jedoch sehr gering. Trotzdem wurde sein Vertrag um ein weiteres Jahr verlängert.

Torhüter Martin Kobras ist der Dauerbrenner im Kader des SCR Altach. Derzeit gibt es keinen Torhüter im Kader der seinen Platz als Nummer 1 streitig machen könnte. Mit Tino Casali wurde jedoch ein 24-jähriger Verpflichtet, der Kobras irgendwann mal beerben könnte.

Johannes Tartarotti und Lars Nussbaumer sind zwei junge Vorarlberger, in denen noch sehr viel Potenzial schlummert. Sie kommen erst in das beste Fußballeralter.

Das Durchschnittsalter der eingesetzten Spieler lag in der vergangenen Saison bei 24,9 Jahren. WAC hat im Vergleich mit 27,5 Jahren den ältesten und Salzburg mit 23,5 den jüngsten Kader eingesetzt.

Liverpool FC – nach 30 Jahren endlich wieder an der Spitze der englischen Premier League

Liverpool FC – nach 30 Jahren endlich wieder an der Spitze der englischen Premier League

Corona hätte Jürgen Klopp und seiner Mannschaft fast einen Strich durch die Rechnung gemacht. Schlussendlich wurde die Saison aber doch fortgesetzt und Liverpool krönt sich nach 30 Jahren wieder zum besten Team in England. In dieser Zeit hat Liverpool beeindruckende Konstanz bewiesen. Nie waren sie schlechter als auf Platz 8 – dies gelang sonst keinem anderen Team. Mit Arsenal, Chelsea, Everton, Manchester United, Tottenham und Liverpool waren gar nur sechs Teams durchgehend in der Premier League vertreten (seit 1989).

In dieser Tabelle sind alle Saisonen seit dem letzten Triumph von Liverpool berücksichtigt (inkl. Meistersaison 1989/1990). Manchester United liegt klar in Führung, gefolgt von Arsenal. Liverpool konnte auf Grund des Rekordvorsprungs in dieser Saison, Chelsea überholen.

Durchschnittlich belegte Liverpool den 4. Platz. Stadtrivale Everton Platz 10. Manchester United hat durchschnittlich die beste Endplatzierung mit 2,77. Liverpool ist mit einer Varianz von 4,32 in den Endplatzierung jedoch mit Abstand am konstantesten.

Die Entwicklung der ÖFB Jugendliga im letzten Jahrzehnt mit Schwerpunkt AKA Vorarlberg U18

Die Entwicklung der ÖFB Jugendliga im letzten Jahrzehnt mit Schwerpunkt AKA Vorarlberg U18

Motiviert durch den Artikel „Die Red Bull DNA“ von Sky Sport Austria, habe ich mir vorgenommen den Jugendfußball in Österreich etwas genauer unter die Lupe zu nehmen. Mit Schwerpunkt auf die Akademie in Vorarlberg (auf Grund meiner Herkunft), deren Abschneiden schon mit freiem Auge als schlecht bezeichnet werden kann. Die verwendeten Daten stammen von transfermarkt.at und wurden händisch erfasst. (Web Scraping ist eines der nächsten Themen mit denen ich mich beschäftigen möchte.)

Bis zur Saison 2013/2014 hieß die Akademie in Kärnten – AKA Kärnten U18. Danach wurde sie übernommen/umbenannt auf AKA WAC U18. Der Einfachheitshalber verwende ich für beide Teams die aktuelle Namensgebung. Dies gilt auch für die Akademie des LASK, Ried und Sturm Graz. Die Saison 2019/2020 wurde bis inklusive 12. Spieltag berücksichtigt. Leider musste auf Grund von Corona der Spielbetrieb abgebrochen werden. Da es in der Jugendliga weder Auf.- noch Absteiger gibt, hat jedes Team die gleiche Anzahl an Spielen absolviert, nämlich 210.

Mit Respektabstand führt Salzburg die 10-Jahres Tabelle an. Deutlich abgeschlagen die U18 aus Vorarlberg. Sogar das kleinere Bundesland Burgenland liegt 23 Punkte vor Vorarlberg. Der Punkteschnitt von Vorarlberg liegt deutlich unter 1 Punkt pro Spiel.

Leider ist mir aufgefallen, dass die Daten von Transfermarkt.at nicht 100%ig korrekt sind. Die geschossenen und erhaltenen Tore unterscheiden sich um 10. Über 10 Saisonen gesehen ist der Fehler aber überschaubar. Im folgenden Plot habe ich die geschossenen und erhaltenen Tore jedes Teams gegenübergestellt um so die Teams zu klassifizieren. Es gibt drei deutlich unterscheidbare Cluster. Salzburg hebt sich natürlich von allen anderen Teams ab. Gefolgt von Austria, Rapid, Admira, St. Pölten und Sturm. Als „Schwacher Angriff, Schwache Abwehr“, würde ich die restlichen Teams Ried, LASK, WAC, Tirol, Burgenland und Vorarlberg klassifizieren.

Im folgenden Plot sind die Endplatzierungen der Teams in den letzten 10 Saisonen dargestellt. Die größte Varianz in den Endplatzierungen hat dabei St. Pölten mit 10,04! Auch LASK und Sturm haben mit Werten >8.00 eine hohe Varianz in den Endplatzierungen. Salzburg, Austria und Tirol performen sehr konstant.

TeamVarianz Endplatzierung
AKA Salzburg U180,93
AKA Austria U181,11
AKA Tirol U181,51
AKA WAC U183,12
Vorarlberg U183,82
AKA Rapid U184,44
AKA Admira U184,54
AKA Bgld. U184,84
AKA SV Ried U185,16
LASK U188,04
Sturm U188,44
St. Pölten U1810,04

Weitere Analysen und ein Blick auf U16 Liga folgen.

Supervised Learning in R: Logistische Regression

Supervised Learning in R: Logistische Regression

Bei der linearen Regression wird versucht eine beobachtete abhängige Variable durch eine oder mehrere unabhängige Variablen zu erklären.

Bei logistischer Regression wird vorher gesagt ob etwas zutrifft oder nicht. Das Ergebnis der logistischen Regression liegt zwischen 0 und 1 und stellt die Wahrscheinlichkeit dar.

In folgendem Beispiel wird das donors.csv Dataset von DataCamp verwendet. Es handelt sich dabei um eine Liste an Spendern mit Informationen über das Alter, Interessen etc. Anhand dieser Daten soll vorher gesagt werden, ob eine Spende zu erwarten ist oder nicht.

Die Daten werden geladen und mit head(), dim() und str() werfen wir einen Blick darauf um ein besseres Gefühl für die Daten zu bekommen. Die Spalte „donated“ ist 1 wenn die entsprechende Person eine Spende getätigt hat, 0 wenn nicht. Dies wird die zu bestimmende Variable in diesem Modell.

donors <- read.csv("https://assets.datacamp.com/production/course_2906/datasets/donors.csv")
head(donors)
dim(donors)
# [1] 93462    13
str(donors)
# 'data.frame':	93462 obs. of  13 variables:
#   $ donated          : int  0 0 0 0 0 0 0 0 0 0 ...
# $ veteran          : int  0 0 0 0 0 0 0 0 0 0 ...
# $ bad_address      : int  0 0 0 0 0 0 0 0 0 0 ...
# $ age              : int  60 46 NA 70 78 NA 38 NA NA 65 ...
# $ has_children     : int  0 1 0 0 1 0 1 0 0 0 ...
# $ wealth_rating    : int  0 3 1 2 1 0 2 3 1 0 ...
# $ interest_veterans: int  0 0 0 0 0 0 0 0 0 0 ...
# $ interest_religion: int  0 0 0 0 1 0 0 0 0 0 ...
# $ pet_owner        : int  0 0 0 0 0 0 1 0 0 0 ...
# $ catalog_shopper  : int  0 0 0 0 1 0 0 0 0 0 ...
# $ recency          : Factor w/ 2 levels "CURRENT","LAPSED": 1 1 1 1 1 1 1 1 1 1 ...
# $ frequency        : Factor w/ 2 levels "FREQUENT","INFREQUENT": 1 1 1 1 1 2 2 1 2 2 ...
# $ money            : Factor w/ 2 levels "HIGH","MEDIUM": 2 1 2 2 2 2 2 2 2 2 ...

Mit der glm() Funktion erstellen wir ein Modell. „donated“ soll mit Hilfe von „bad_address“, „interest_religion“ und „interest_veterans“ modelliert werden.

donation_model <- glm(donated ~ bad_address + interest_religion + interest_veterans, data = donors, family = "binomial")
summary(donation_model)

Die Funktion predict() auf das Modell angewendet, gibt uns die Vorhersage für zukünftiges Verhalten. Als default werden log odds zurück gegeben. Der Parameter type = „response“ wandelt diese in Wahrscheinlichkeiten um. Die durchschnittliche Wahrscheinlichkeit einer Spende liegt bei 0,0504. Liegt die Wahrscheinlichkeit jeder einzelnen Person über dem Durchschnitt, wird in der Spalte „donation_pred“ 1 eingetragen. Mit mean() können wir die Genauigkeit des Modell berechnen.

donors$donation_prob <- predict(donation_model, type = "response")

mean(donors$donated)
# [1] 0.05040551

donors$donation_pred <- ifelse(donors$donation_prob > 0.0504, 1, 0)

mean(donors$donation_pred == donors$donated)
# [1] 0.794815

79,48 % Genauigkeit klingt zwar gut, ist es aber nicht! Wenn man für alle Personen 0 vorher gesagt hätte, hätte man schon eine Genauigkeit von 95 %! Die ROC Kurve kann uns zeigen, wie gut ein Modell wirklich ist. Die Area Under the Curve (AUC) gibt uns einen Wert der zwischen 0 und 1 liegt. Wir benötigen dazu das „pROC“ Package und die Funktionen roc() und auc().

library(pROC)
ROC <- roc(donors$donated, donors$donation_prob)
plot(ROC, col = "blue")
auc(ROC)
# Area under the curve: 0.5102

Die blaue Linie liegt sehr nahe an der Baseline. In diesem Fall ist das Modell nicht wirklich verwendbar.

.

Supervised Learning in R: Bayesian Methods

Supervised Learning in R: Bayesian Methods

Mobiltelefone tracken mittlerweile jeden Schritt von uns. Diese Daten geben nicht nur Aufschluss an welchen Orten wir waren, sondern auch wo wir uns mit einer großen Wahrscheinlichkeit zukünftig befinden werden.

Angenommen das Handy hat festgehalten, dass wir uns 3 Mal in einem Restaurant, 10 Mal zu Hause, 4 Mal in einem Shop und 23 Mal bei der Arbeit befunden haben. Mit einer Wahrscheinlichkeit von 57,5 % (23/40) befinden wir uns also bei der Arbeit. Nicht besonders aussagekräftig für zukünftige Zeitpunkte. Kommt allerdings eine weitere Variable dazu, z.B. die Zeit, dann können schon um einiges genauere Vorhersagen getroffen werden.

Der Satz von Bayes wurde nach dem Mathematiker Thomas Bayes benannt. Er beschreibt die Berechnung von bedingten Wahrscheinlichkeiten. Also z.B. wie wahrscheinlich ist es, dass ich bei der Arbeit bin, wenn gerade Montag 9 Uhr ist.

In folgendem Beispiel wird der Datensatz locations.csv von DataCamp und die library „e1071“ verwendet. Zuerst werden die Daten eingelesen und mit head(), dim() und str() erhalten wir einen Überblick über die Daten.

library(e1071)

locations <- read.csv("R/locations.csv", header = TRUE, sep = ",")
head(locations)
# month day   weekday daytype hour hourtype location
# 1     1   4 wednesday weekday    0    night     home
# 2     1   4 wednesday weekday    1    night     home
# 3     1   4 wednesday weekday    2    night     home
# 4     1   4 wednesday weekday    3    night     home
# 5     1   4 wednesday weekday    4    night     home
# 6     1   4 wednesday weekday    5    night     home
dim(locations)
# [1] 2184    7

str(locations)
# 'data.frame':	2184 obs. of  7 variables:
#   $ month   : int  1 1 1 1 1 1 1 1 1 1 ...
# $ day     : int  4 4 4 4 4 4 4 4 4 4 ...
# $ weekday : Factor w/ 7 levels "friday","monday",..: 7 7 7 7 7 7 7 7 7 7 ...
# $ daytype : Factor w/ 2 levels "weekday","weekend": 1 1 1 1 1 1 1 1 1 1 ...
# $ hour    : int  0 1 2 3 4 5 6 7 8 9 ...
# $ hourtype: Factor w/ 4 levels "afternoon","evening",..: 4 4 4 4 4 4 3 3 3 3 ...
# $ location: Factor w/ 7 levels "appointment",..: 3 3 3 3 3 3 3 3 3 4 ...

Dann erstellen wir mit naiveBayes() unser Model. Wir wollen die Location vorher sagen anhand der Tages Art und der Stunde. Mit laplace = 1 wir die Berechnung etwas geglättet. Das heißt, auch Ereignisse, welche in den Trainingsdaten nicht vorkommen werden mit einbezogen.

locationmodel <- e1071::naiveBayes(location ~ daytype + hour, data = locations, laplace=1)

Jetzt wollen wir natürlich überprüfen, was unser Model für einen bestimmten Zeitpunkt in der Zukunft vorhersagt. Als Beispiel habe ich ein DataFrame mit „weekday“ und 6 Uhr erstellt.

daytype <- "weekday"
futurelocation <- data.frame(daytype)
futurelocation$hour <- 6

Die predict() Funktion gefüttert mit dem Model und dem zu vorhersagenden Zeitpunkt, liefert uns als Ergebnis „home“. Wird der Parameter „type“ der predict Funktion auf „raw“ gesetzt, sehen wir die Wahrscheinlichkeiten aller möglichen Orte.

predict(locationmodel, futurelocation)
# [1] home

predict(locationmodel, futurelocation, type="raw")
# appointment     campus      home     office restaurant        store      theater
# [1,] 0.0004453673 0.02000083 0.9327182 0.03388309 0.01295256 9.182049e-23 9.926374e-49
DataCamp Potcast

DataCamp Potcast

Ich bin ein Stammhörer des Postcasts von DataCamp, genannt DataFramed. Wöchentlich werden Personen aus dem Bereich von Data Analytics, Data Science oder anderen verwandten Themen interviewt. Diese Woche erschien ein besonders interessanter Potcast für mich. „Data Science, Gambling and Bookmaking (with Marco Blume)“. Marco Blume ist Trading Director bei Pinnacle Sports, einem der größten und besten Buchmacher der Welt.

Postcast mit Pinnacle Trading Director Marco Blume

Pinnacle ist bekannt für hohe Limits, niedrige Margen und „Winning Players accepted“. Spieler welche die Quoten von Pinnacle schlagen werden nicht limitiert wie bei anderen Buchmachern, sondern werden als „Superforcaster“ verwendet. In diesem Zusammenhang wurde auch das Buch „Superforecasting: The Art and Science of Prediction“ von Philip Tetlock erwähnt. Sehr interessant für mich war, dass Pinnacle hauptsächlich R verwendet.

Supervised Learning in R: k-Nearest Neighbors

Supervised Learning in R: k-Nearest Neighbors

Supervised Learning ist eine Unterkategorie des Machine Learnings. Mit Hilfe von gelabelten Daten wird ein Algorithmus gelernt, welcher dann auf ungelabelte Test-Daten angewendet werden kann. Eine Anwendungsmöglichkeit ist zum Beispiel Bilderkennung.

Der k-Nearest Neighbors (kNN) Algorithmus eignet sich hervorragend für Klassifikationsprobleme. Ein Datensatz wird anhand seiner nächsten Nachbarn klassifiziert. k gibt an wie viele Nachbarn in Betracht gezogen werden sollen. Für die Anwendung benötigt es das Package „class“, einen Training Datensatz, einen Test Datensatz und die passenden Labels.

Als Datensatz verwende ich Verkehrsschilder, welche von DataCamp zur Verfügung gestellt werden. Bei der Aufbereitung wurden die Bilder von den Verkehrsschildern in eine 4×4 Matrix aufgeteilt und in jedem Feld die RGB Werte gemessen. Das heißt, wir haben 48 Datenpunkte pro Bild. Unsere Aufgabe ist es, den Datensatz noch in einen Training Datensatz, Test Datensatz und die Labels aufzuteilen.

data <- read.csv("https://assets.datacamp.com/production/repositories/718/datasets/c274ea22cc3d7e12d7bb9fdc9c2bdabe9ab025f4/knn_traffic_signs.csv", header = TRUE, sep = ",")

signs <- subset(data, sample == "train")
signs$sample <- NULL
signs$id <- NULL

test.data <- subset(data, sample == "test")
test.data$id <- NULL
test.data$sample <- NULL

sign_types <- signs$sign_type
signs_actual <- test.data$sign_type

Dann kann der knn Algorithmus auf die Daten angewendet werden. [-1] weil in der ersten Spalte das Label steht und wir den Algo natürlich nicht mit diesem Wissen füttern wollen.

signs_pred <- knn(train = signs[-1], test = test.data[-1], cl = sign_types)
table(signs_pred, signs_actual)
mean(signs_pred == signs_actual)

kNN konnte 93,2 % der Straßenschilder richtig einteilen.

Als default verwendet der kNN Algorithmus vom class Package nur einen nearest neighbor. Mit dem Parameter k, können wir eine beliebige Anzahl an nearest neighbors angeben und versuchen so die Genauigkeit weiter zu verbessern.

k_1 <- knn(train = signs[-1], test = test.data[-1], cl = sign_types)
mean(k_1==signs_actual)
table(k_1, signs_actual)
# 0.9322034
# signs_actual
# k_1          pedestrian speed stop
# pedestrian         19     2    0
# speed               0    17    0
# stop                0     2   19

k_7 <- knn(train = signs[-1], test = test.data[-1], cl = sign_types, k = 7)
mean(k_7==signs_actual)
table(k_7, signs_actual)
# 0.9661017
# signs_actual
# k_7          pedestrian speed stop
# pedestrian         18     0    0
# speed               0    20    0
# stop                1     1   19

k_15 <- knn(train = signs[-1], test = test.data[-1], cl = sign_types, k = 15)
mean(k_15==signs_actual)
table(k_15, signs_actual)
# 0.8813559
# signs_actual
# k_15         pedestrian speed stop
# pedestrian         13     0    0
# speed               1    20    0
# stop                5     1   19

Mit k = 7 konnte schon ein sehr gutes Ergebnis erzielt werden. 96,6 % der Schilder wurden richtig kategorisiert.

Telegram Bot – Nachrichten via RStudio versenden

Telegram Bot – Nachrichten via RStudio versenden

Ich habe ein R-Script entwickelt, welches mir Surebets im Wettmarkt sucht. Surebets sind wie der Name schon sagt sichere Wetten. Das heißt, man kann bei schlauem Verteilen des Einsatzes auf jeden Fall Gewinn machen. Als Beispiel nehme ich das klassische Beispiel eines Tennis Matches. Spieler A kann man bei Buchmacher 1 zu Quote 2,10 und Spieler B kann man bei Buchmacher 2 ebenfalls zu Quote 2,10 tippen. Das heißt, wenn ich nun auf beide Spieler jeweils 100 Euro setze, habe ich egal wie das Spiel ausgeht, 10 Euro Gewinn nach dem Spiel. Bitte beachten, dass dies ein fiktives Beispiel ist. Bei Tennis Wetten muss zB auch die w.o. Regel des jeweiligen Buchmachers berücksichtigt werden.

Zurück zum ursprünglichen Thema. Bis jetzt wurde ich immer mit einem lauten Beep Ton informiert, wenn mein Programm eine Surebet gefunden hat. Ich würde es aber komfortabler finden eine Nachricht auf mein Smartphone zu bekommen. Hier bietet sich ein Telegram Bot an.

Telegram bietet eine API für solche Bots an und in R gibt es ein passendes Package dazu. Zuerst muss der botfather angeschrieben werden, um einen Bot erstellen zu können.

Mit /newbot kann ein neuer Bot erstellt werden. Einfach ein paar Fragen des BotFather beantworten und schon erhält man einen Token für die API. Den Bot fügt man jetzt am besten der .Renviron File hinzu. Diese kann mit folgendem Code erstellt werden:

user_renviron = path.expand(file.path("~", ".Renviron"))
if(!file.exists(user_renviron)) # check to see if the file already exists
  file.create(user_renviron)
file.edit(user_renviron) # open with another text editor if this fails

Wer es genauer wissen will, kann hier mehr darüber erfahren. In diese File schreiben wir dann folgenden Befehl mit dem Token.

R_TELEGRAM_BOT_SurebetBot=Eigener_Token

Danach ist wichtig, dass RStudio neu gestartet wird. Mit folgendem Code kann dann eine Message versendet werden.

library(telegram)
bot <- TGBot$new(token = bot_token('Bot_Name'))
bot$set_default_chat_id(123456)
bot$sendMessage('Hallo, ich bin dein Telegram Bot')

Anstelle von 123456 muss die passende Chat ID eingefügt werden. Diese ID kann man durch die URL https://api.telegram.org/bot<API-access-token>/getUpdates?offset=0 herausfinden. Anstelle von <API-access-token> die eigene Token ID angeben. Zurück kommt ein JSON String in dem man unter chat: id: die passende ID herauslesen kann. Damit dies funktioniert, muss zuvor aber schon mindestens eine Nachricht an den Bot geschickt worden sein.

Shiny für Python

Shiny für Python

Ich habe im Sommer die ersten Erfahrungen mit Shiny in R gemacht. Da ich momentan Python lerne, möchte ich etwas gleichwertiges haben und bin dabei auf Dash gestoßen. Hier mein erster Gehversuch:

Zuerst mal die benötigten Packages installieren.

pip install dash==0.35.1 
pip install dash-html-components==0.13.4
pip install dash-core-components==0.42.1
pip install dash-table==3.1.11

Neue app.py File erstellen und Beispiel Code einfügen.

import dash
import dash_core_components as dcc
import dash_html_components as html

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

app.layout = html.Div(children=[
    html.H1(children='Hello Dash'),

    html.Div(children='''
        Dash: A web application framework for Python.
    '''),

    dcc.Graph(
        id='example-graph',
        figure={
            'data': [
                {'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'bar', 'name': 'SF'},
                {'x': [1, 2, 3], 'y': [2, 4, 5], 'type': 'bar', 'name': u'Montréal'},
            ],
            'layout': {
                'title': 'Dash Data Visualization'
            }
        }
    )
])

if __name__ == '__main__':
    app.run_server(debug=True)

Die Datei app.py ausführen et voilà – die erste Dash App kann unter localhost:8050 im Browser geöffnet werden.

Der Code-Aufbau ähnelt sehr dem von Shiny. Wer als schon Erfahrung mit Shiny und R hat, sollte hier sehr schnell rein finden.

Dieses und weitere Code Beispiele gibt es auf der Webseite von Dash.

Soccer Analytics

Soccer Analytics

Die Amerikaner sind ein Sportbegeistertes Volk. Sie lieben ihre Sport-Helden und deren Leistungen und Rekorde. In den 90er Jahren revolutionierte Billy Beane die MLB mit seiner neuen Art Spieler zu bewerten. Heute auch bekannt als Sabermetrics. Seine Geschichte wurde im Film „Moneyball„, in der Hauptrolle kein geringerer als Brad Pitt, verfilmt.

Erst einige Jahre später wurden die Vorteile von Datenanalysen im Fußballbereich entdeckt. Videoanalysen gehören zu Standardrepertoire eines Fußballvereins, aber zB die Auswertung von Positionsdaten steckt noch in den Kinderschuhen.

Datenanalyse kann in vielen Bereichen eines Profiteams eingesetzt werden. So können zB Verletzungen von Spielern vorher gesagt werden mit den passenden Daten. Vergleichbar mit Predictive Maintenance bei Maschinen. Das AC Milan Lab gehört hier zu den Vorreitern und hat dem Verein schon Millionen gespart.

Ein weiteres Beispiel ist Matthew Benham. Der Gründer von Smartodds wurde reich mit der Entwicklung von Algorithmen, welche die Wahrscheinlichkeiten für Fußballergebnisse berechnen. Er ist Besitzer des FC Brentford in England und des dänische Vereins FC Midtjylland, welche beide vom Know-How von Benham und seinem Team profitieren.

In den Top Ligen Europas, gibt es wohl kaum noch eine Mannschaft die nicht auf das Hilfsmittel der Datenanalyse baut. In der englischen Premier League ist es sogar üblich eine ganze Abteilung mit Mathematikern und Statistikern zu haben. Manchester City veranstaltet Hackathons um neue innovative Ideen zu sammeln und den Gegnern vielleicht einen Schritt voraus zu sein.

Dank großer Datenprovider wie Opta Sports, STATS und Sportradar haben auch kleinere Vereine Zugang zu wertvollen Daten. Nur leider haben diese Teams oft nicht die nötigen Ressourcen um mit solchen Daten etwas anzufangen.