Analyse der Altersstruktur des SCR Altach-Kaders

Analyse der Altersstruktur des SCR Altach-Kaders

Ich habe die Altersstruktur des Kaders des SC Rheindorf Altach analysiert und die Ergebnisse in einer Grafik visualisiert, die das Alter der Spieler mit ihrem Anteil an den Einsatzminuten der vergangenen Saison vergleicht. Diese Gegenüberstellung zeigt interessante Trends und Einblicke in die strategische Ausrichtung des Vereins.

Philipp Netzer ist mit Abstand der älteste Spieler im Kader. Aufgrund einer Verletzung konnte er nur eine sehr begrenzte Anzahl an Minuten auf dem Platz stehen. Trotz seiner eingeschränkten Einsatzzeit entschied sich der Verein, seinen Vertrag um ein weiteres Jahr zu verlängern – eine Entscheidung, die auf seine Führungserfahrung und Bedeutung für das Team hinweisen könnte.

Martin Kobras, der Torhüter und Dauerbrenner des Teams, nimmt weiterhin eine Schlüsselrolle ein. Bisher gibt es im Kader keinen ernsthaften Konkurrenten, der seine Position als Nummer 1 gefährden könnte. Der 24-jährige Tino Casali, der kürzlich verpflichtet wurde, könnte langfristig jedoch eine Option sein, um Kobras in Zukunft zu ersetzen.

Besonders spannend sind die jungen Vorarlberger Talente Johannes Tartarotti und Lars Nussbaumer. Beide stehen noch am Anfang ihrer Karriere und besitzen das Potenzial, sich in den kommenden Jahren zu Schlüsselspielern zu entwickeln, da sie sich nun in das optimale Fußballeralter bewegen.

Die Statistik zeigt, dass das Durchschnittsalter der eingesetzten Spieler in der letzten Saison bei 24,9 Jahren lag. Damit positioniert sich der SCR Altach zwischen den älteren und jüngeren Teams der Liga: Während der Wolfsberger AC mit 27,5 Jahren den ältesten Kader stellte, setzte Red Bull Salzburg mit einem Durchschnittsalter von 23,5 Jahren auf Jugend und Dynamik.

Liverpool FC: Nach 30 Jahren zurück an der Spitze der Premier League

Liverpool FC: Nach 30 Jahren zurück an der Spitze der Premier League

Die Corona-Pandemie hätte Jürgen Klopp und seinem Team beinahe einen Strich durch die Meisterträume gemacht. Doch letztlich konnte die Saison fortgesetzt werden, und Liverpool krönte sich nach 30 langen Jahren endlich wieder zum besten Team Englands. Die Dominanz in dieser Spielzeit ist ein krönender Abschluss jahrelanger Konstanz und herausragender Arbeit.

Seit dem Beginn der Premier League-Zeit hat Liverpool eine beeindruckende Stabilität bewiesen. Kein einziges Mal fiel die Mannschaft in der Endabrechnung unter Platz 8 – eine Leistung, die kein anderes Team vorweisen kann. Tatsächlich sind nur sechs Vereine seit der Gründung der Premier League im Jahr 1989 ununterbrochen in der Liga vertreten: Arsenal, Chelsea, Everton, Manchester United, Tottenham und Liverpool.

Dieser Tabelle bietet einen Überblick über die Platzierungen der Top-Teams seit Liverpools letzter Meisterschaft in der Saison 1989/1990. Manchester United führt klar in der Gesamtwertung, gefolgt von Arsenal. Doch dank des Rekordvorsprungs in dieser Saison konnte Liverpool Chelsea in der ewigen Tabelle überholen.

Im Durchschnitt belegte Liverpool den 4. Platz in diesen 30 Jahren, während Stadtrivale Everton durchschnittlich auf Platz 10 landete. Manchester United weist mit einem Durchschnitt von 2,77 die beste Endplatzierung auf. Bemerkenswert ist aber Liverpools Konstanz: Mit einer Varianz von 4,32 in den Endplatzierungen ist die Mannschaft mit Abstand die konstanteste Kraft in der Liga – ein Zeugnis für ihre langanhaltende Wettbewerbsfähigkeit.

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

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

Inspiriert durch den Artikel Die Red Bull DNA von Sky Sport Austria habe ich beschlossen, einen genaueren Blick auf die Entwicklung des Jugendfußballs in Österreich zu werfen. Im Fokus steht dabei die Akademie in Vorarlberg, die aufgrund ihrer Leistung in den letzten Jahren als eine der schwächeren Mannschaften gilt. Die Daten für diese Analyse stammen von transfermarkt.at und wurden manuell erfasst. (Web Scraping ist ein Thema, das ich bald vertiefen möchte.)

Einige organisatorische Änderungen prägen die betrachtete Periode: Bis zur Saison 2013/2014 firmierte die Akademie in Kärnten unter dem Namen AKA Kärnten U18, bevor sie als AKA WAC U18 weitergeführt wurde. Der Einfachheit halber verwende ich in der gesamten Analyse die aktuellen Bezeichnungen, was auch für die Akademien von LASK, Ried und Sturm Graz gilt. Für die Saison 2019/2020 wurden nur die ersten 12 Spieltage berücksichtigt, da die Corona-Pandemie den Spielbetrieb vorzeitig beendete. Da es in der Jugendliga weder Auf- noch Absteiger gibt, hatte jedes Team die gleiche Anzahl von 210 Spielen über den betrachteten Zeitraum.

Ein Blick auf die 10-Jahres-Tabelle zeigt eine klare Dominanz von Salzburg, die sich mit großem Vorsprung an der Spitze befindet. Am anderen Ende der Tabelle rangiert die AKA Vorarlberg U18, die sogar von der Akademie des kleineren Bundeslandes Burgenland um 23 Punkte übertroffen wird. Der Punkteschnitt von Vorarlberg liegt signifikant unter einem Punkt pro Spiel, was die Leistungsschwäche unterstreicht.

Es ist wichtig anzumerken, dass die Daten von transfermarkt.at kleinere Unstimmigkeiten aufweisen: Die Anzahl der geschossenen und erhaltenen Tore weicht um 10 Treffer voneinander ab. Über den Zeitraum von 10 Saisons bleibt dieser Fehler jedoch im akzeptablen Bereich. Der folgende Plot stellt die geschossenen Tore den erhaltenen Toren gegenüber, um die Teams zu klassifizieren. Hier zeigen sich drei klar unterscheidbare Cluster: Salzburg hebt sich deutlich von allen anderen Teams ab. Dahinter folgen Austria, Rapid, Admira, St. Pölten und Sturm. Die verbleibenden Mannschaften – Ried, LASK, WAC, Tirol, Burgenland und Vorarlberg – lassen sich unter der Kategorie „Schwacher Angriff, schwache Abwehr“ zusammenfassen.

Ein weiteres interessantes Merkmal ist die Varianz der Endplatzierungen über die letzten 10 Saisons. St. Pölten zeigt hier mit einem Wert von 10,04 die höchste Schwankung, gefolgt von LASK und Sturm, die ebenfalls Varianzen über 8,00 aufweisen. Im Gegensatz dazu sind die Leistungen von Salzburg, Austria und Tirol deutlich konstanter.

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

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 Podcast: Einblicke in Data Science, Glücksspiel und Buchmacherei

DataCamp Podcast: Einblicke in Data Science, Glücksspiel und Buchmacherei

Ich bin ein begeisterter Hörer des DataCamp-Podcasts DataFramed. Wöchentlich werden dort Experten aus den Bereichen Data Analytics, Data Science und verwandten Feldern interviewt. Besonders spannend fand ich die neueste Episode mit dem Titel „Data Science, Gambling, and Bookmaking“, in der Marco Blume, der Trading Director von Pinnacle Sports, zu Gast war.

Postcast mit Pinnacle Trading Director Marco Blume

Pinnacle Sports ist weltweit bekannt für seine hohen Wettlimits, niedrigen Margen und die Politik „Winning Players accepted“. Anders als viele andere Buchmacher limitiert Pinnacle Spieler, die ihre Quoten schlagen, nicht. Stattdessen werden diese erfolgreichen Wetter, auch „Superforecaster“ genannt, aktiv genutzt, um die eigenen Quotenmodelle zu verbessern. Im Gespräch erwähnt Marco Blume auch das Buch Superforecasting: The Art and Science of Prediction von Philip Tetlock, das die Wissenschaft und Kunst präziser Vorhersagen beleuchtet.

Ein Aspekt, der für mich besonders interessant war, ist die Tatsache, dass Pinnacle für viele seiner Datenanalysen und Modellierungen auf die Programmiersprache R setzt. Dies unterstreicht, wie weit verbreitet und leistungsfähig R im Bereich der professionellen Datenanalyse ist, selbst in der komplexen Welt des Sportwettens.

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.

Automatisierte Surebet-Benachrichtigungen mit einem R-Script und einem Telegram-Bot

Automatisierte Surebet-Benachrichtigungen mit einem R-Script und einem Telegram-Bot

Ich habe ein R-Script entwickelt, das Surebets auf dem Wettmarkt identifiziert. Surebets, wie der Name schon sagt, sind sichere Wetten, bei denen man durch eine clevere Verteilung des Einsatzes garantiert Gewinn machen kann. Um dies zu verdeutlichen, nehmen wir ein klassisches Beispiel aus dem Tennis: Angenommen, Spieler A wird bei Buchmacher 1 zu einer Quote von 2,10 angeboten, und Spieler B ist bei Buchmacher 2 ebenfalls zu einer Quote von 2,10 spielbar. Setzt man jeweils 100 Euro auf beide Spieler, ergibt sich ein sicherer Gewinn von 10 Euro, unabhängig vom Ausgang des Spiels. Dieses Beispiel ist natürlich fiktiv, und in der Praxis müssen auch die speziellen Wettregeln, wie etwa die „w.o.“-Regel bei Tennisspielen, beachtet werden.

Bis jetzt hat mein Programm mich durch einen lauten Beep-Ton alarmiert, wenn eine Surebet entdeckt wurde. Um es komfortabler zu gestalten, möchte ich nun Benachrichtigungen direkt auf mein Smartphone erhalten. Eine praktische Lösung dafür ist die Verwendung eines Telegram-Bots.

Telegram bietet eine API, die die Erstellung und Integration solcher Bots ermöglicht, und es gibt ein passendes R-Package, um diese API zu nutzen. Der erste Schritt ist die Erstellung eines Bots über den „BotFather“ in Telegram.

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: Wie Daten den Fußball revolutionieren

Soccer Analytics: Wie Daten den Fußball revolutionieren

Die Amerikaner sind bekannt für ihre Begeisterung für Sport und ihre Verehrung von Sporthelden, deren Leistungen in einer Vielzahl von Statistiken und Rekorden dokumentiert werden. In den 1990er Jahren veränderte Billy Beane die Major League Baseball (MLB) grundlegend, indem er eine neue Methode zur Bewertung von Spielern einführte, die heute als Sabermetrics bekannt ist. Seine Geschichte wurde im Film Moneyball mit Brad Pitt in der Hauptrolle eindrucksvoll verfilmt.

Es dauerte jedoch einige Jahre, bis die Vorteile datengetriebener Analysen auch im Fußball erkannt wurden. Während Videoanalysen inzwischen zum Standardrepertoire eines jeden professionellen Vereins gehören, steckt die Nutzung fortschrittlicher Daten wie etwa Positionsdaten noch in den Kinderschuhen.

Die Möglichkeiten, die Datenanalysen im Fußball bieten, sind vielfältig. Ein spannender Anwendungsbereich ist die Prävention von Verletzungen. Mit den richtigen Datensätzen können Verletzungen vorhergesagt werden – ein Konzept, das dem Predictive Maintenance-Ansatz in der Industrie ähnelt. Das AC Milan Lab ist in diesem Bereich ein Pionier und hat dem Verein durch proaktive Maßnahmen zur Vermeidung von Spielerausfällen bereits Millionen eingespart.

Ein weiteres faszinierendes Beispiel ist Matthew Benham, Gründer von Smartodds. Benham hat ein Vermögen mit der Entwicklung von Algorithmen verdient, die die Wahrscheinlichkeiten von Fußballergebnissen berechnen. Seine Expertise hat er auf den Fußball übertragen: Als Besitzer des FC Brentford in England und des dänischen Vereins FC Midtjylland setzt er auf datengetriebene Strategien, die beiden Clubs einen Wettbewerbsvorteil verschaffen.

In den europäischen Top-Ligen ist Datenanalyse mittlerweile unverzichtbar. In der englischen Premier League zum Beispiel ist es üblich, ganze Abteilungen von Mathematikern und Statistikern zu beschäftigen, um datenbasierte Einblicke zu gewinnen. Manchester City organisiert sogar regelmäßig Hackathons, um innovative Ideen zu sammeln und stets einen Schritt voraus zu sein.

Dank großer Datenanbieter wie Opta Sports, STATS und Sportradar haben inzwischen auch kleinere Vereine Zugang zu hochwertigen Daten. Allerdings fehlen diesen Teams oft die Ressourcen, um diese Daten effektiv zu nutzen. Dennoch zeigt sich: Die Bedeutung von Soccer Analytics wächst stetig, und es ist nur eine Frage der Zeit, bis datengetriebene Strategien auch die unteren Ligen nachhaltig prägen.