En dataanalyse av 940 000+ kamphendelser fra fem toppligaer ved hjelp av Python, NetworkX og SQL.
Bakgrunn og datagrunnlag
Denne analysen tar utgangspunkt i et datasett med over 940 000 kamphendelser fra fem europeiske ligaer (Bundesliga, Serie A, La Liga, Ligue 1 og Premier League) over flere sesonger. Dataene er lagret i en MySQL-database og inneholder én rad per hendelse – frispark, corner, skudd, kort, innbyttinger og mer – med tilhørende kamp-ID, tidsangivelse, lag og tekstbeskrivelse.
| Hendelsestype | Antall |
|---|---|
| Free kick won (frispark vunnet) | 237 932 |
| Foul (frispark mot) | 232 925 |
| Attempt (skudd) | 229 135 |
| Corner | 91 204 |
| Substitution (innbytte) | 51 738 |
| Offside | 43 476 |
| Yellow card | 39 911 |
| Hand ball, Red card, m.fl. | ~14 000 |
Av de 229 135 skuddene endte 24 446 (10,7 %) i mål – identifisert via kolonnen is_goal.
Metode
Teknisk oppsett
Analysen er gjennomført i en Jupyter Notebook med følgende teknologistakk:
- Python 3.14 med
pandas,numpy,matplotlib - NetworkX for grafanalyse og visualisering av hendelsessekvenser
- SQLAlchemy + PyMySQL for tilkobling til MySQL-databasen
from sqlalchemy import create_engine
import pandas as pd
engine = create_engine('mysql+pymysql://bruker:passord@host:3307/fotballdata')
df_events = pd.read_sql("""
SELECT * FROM events A
INNER JOIN event_type B ON A.event_type = B.idx
""", con=engine)
Analyse 1 – Hendelsessekvens-graf (NetworkX)
For å forstå hvilke hendelseskjeder som typisk leder frem til et skudd, ble det bygget en rettet vektet graf (DiGraph) der:
- Noder = hendelsestyper (Corner, Foul, Free kick won, Attempt, Goal, …)
- Kanter = overgang mellom to hendelsestyper i en sekvens
- Kantvekt = antall ganger overgangen forekom i datasettet
For hvert Attempt- eller Goal-event ble de K = 4 foregående hendelsene i samme kamp (etter sort_order) hentet ut. Alle konsekutive par i denne sekvensen ble lagt til som kanter, og selvkanter (samme hendelse to ganger på rad) ble filtrert bort.
K = 4
transitions = collections.Counter()
for _, grp in df_g.groupby('id_odsp'):
labels = grp['event_label'].tolist()
for i, label in enumerate(labels):
if label not in {'Attempt', 'Goal'}:
continue
seq = labels[max(0, i - K) : i + 1]
for a, b in zip(seq, seq[1:]):
if a != b:
transitions[(a, b)] += 1
Analyse 2 – Konverteringsrate per situasjon
Kun Attempt-rader ble brukt. Konverteringsrate ble beregnet som is_goal.mean() × 100 gruppert på:
situation– situasjonstype (åpent spill, frispark, corner, straffe)fast_break– flagg for kontring (0 / 1)assist_method– assisttype (pasning, innlegg, gjennombrudd, m.m.)
Resultater
Topp 10 hendelsesoverganger som leder til skudd
| Fra | Til | Antall |
|---|---|---|
| Foul | Free kick won | 109 205 |
| Free kick won | Foul | 79 236 |
| Free kick won | Attempt | 73 128 |
| Corner | Attempt | 69 607 |
| Foul | Attempt | 44 978 |
| Attempt | Corner | 40 098 |
| Attempt | Foul | 23 154 |
| Substitution | Attempt | 23 061 |
| Yellow card | Attempt | 20 858 |
| Offside | Attempt | 19 096 |
Konverteringsrate per situasjonstype
Kontring vs. normalt spill
Kontringer er 3,5 ganger mer effektive enn skudd fra normalt spill, til tross for at de utgjør under 2 % av alle skudd.
Konverteringsrate per assisttype
Tekstbasert analyse
Nøkkelord som «counter» og «intercept» fantes ikke i text-feltet, da dette beskriver selve avslutningen (fotsted, posisjon, utfall) – ikke forhistorien. Kontringer fanges i stedet opp av den dedikerte fast_break-kolonnen.
Ligaanalyse — fem europeiske toppligaer
Alle fem ligaene har overraskende like konverteringsrater (10,0–11,2 %), men spillestilene skiller seg klart på kontring-andelen.

Tidsanalyse — konverteringsrate gjennom kampen
Konverteringsraten stiger jevnt gjennom kampen: fra 9,8 % i de første 15 minuttene til 12,0 % i overtiden. Samtidig øker det totale skuddvolumet mot slutten av ordinær tid (76–90 min: 46 356 skudd — flest i noen periode).

Konklusjoner
- Kontringer er de farligste situasjonene (35,8 %). Selv om de er sjeldne (~2 % av alle skudd), er konverteringsraten mer enn tre ganger høyere enn for normalt spill. En defensiv feil i overgangsfasen er svært kostbar.
- Gjennombruddsballer gir de beste sjansene (26,0 %). Å spille ballen bak forsvarsrekken er markant mer effektivt enn kombinasjonsspill og innlegg fra siden.
- Dødball dominerer antallsmessig. Corner → Attempt (69 607) og Free kick won → Attempt (73 128) er de hyppigste direkte veiene til skudd. Set pieces er en kritisk del av offensivt spill.
- Skudd utenfor 16-meteren er nesten aldri lønnsomme (2,7 %). 97 av 100 langskudd ender uten mål – men de gir ofte reboundmuligheter (corner / blokkert).
- Attempt → Corner (40 098) viser pressbølger. Mange skudd blokkeres til corner, som igjen gir nytt press – en selvforsterkende angrepssyklus.
- Bundesliga er kontring-ligaen (3,0 %). Premier League bruker kontring minst (1,0 %). Totalt er konverteringsratene likevel nær like (10,0–11,2 %) på tvers av de fem ligaene.
- Kampens siste kvartal er det farligste (11,3 %). Skuddvolumet topper seg i 76–90-perioden (46 356 skudd), og konverteringsraten er klart høyere enn tidlig i kampen (9,8 % i 0–15 min). Trøtthet og åpne rekker gir et taktisk vindu i sluttfasen.
- Composure skiller elitespillere fra gjennomsnittet. FIFA-analysen viser at ro under press (+21 poeng for angripere) er den enkeltegenskapen som gjennomgående differensierer toppspillere i alle roller.
Spillerattributter og rolleanalyse (FIFA 19-data)
For å forstå hvem som skaper målsjanser, ble hendelsesdataene koblet mot FIFA 19-spillerdatabasen (16 654 spillere) via en speilkobling (events.player_fixed → players.idx_fifa → Data.ID). Totalt 163 167 skudd (71,2 %) fikk et gyldig FIFA-oppslag, fordelt på 3 043 unike spillere.
FIFA-rating vs. faktisk konverteringsrate
Scatter-plottet nedanfor viser samanhengen mellom FIFA-attributtar og reell konverteringsrate for spelarar med ≥ 20 skudd i datasettet. Dei sterkaste korrelasjonane mot konverteringsrate er HeadingAccuracy (r = +0,19) og Finishing (r = +0,17). SprintSpeed har ingen statistisk samanheng (r = −0,02).

Hvilke attributter kjennetegner hver rolle?
Radardiagrammene nedenfor viser gjennomsnittlig FIFA-rating per posisjonskategori — med rollespesifikke attributter for hver kategori. Det gir et mer presist bilde enn å sammenligne alle roller på de samme egenskapene.

Hva skiller elitespillere fra gjennomsnittsspillere i hver rolle?
Spillere med Overall ≥ 85 (elite) og Overall 65–74 (gjennomsnitt) ble sammenliknet på nøkkelattributter for hver rolle. De største gapene:

Hvilke FIFA-attributter korrelerer med Overall innenfor hver rolle?
Pearson-korrelasjon mot Overall-rating (FIFA sin samlede vurdering av spilleren i sin rolle):
| Rolle | Sterkaste korrelasjonar |
|---|---|
| Forsvar | StandingTackle r = +0,88 · Interceptions r = +0,88 · Marking r = +0,84 |
| Midtbane | BallControl r = +0,89 · ShortPassing r = +0,83 · Vision r = +0,79 |
| Angrep | BallControl r = +0,90 · Positioning r = +0,89 · Composure r = +0,84 |
| Keeper | GKReflexes r = +0,91 · GKDiving r = +0,89 · GKPositioning r = +0,88 |
Topp 15 spelarar per posisjonskategori (FIFA 19)
Rangert etter Overall-rating. Annotert med nøkkelattributter for rollen. Den stiplede linjen markerer elite-grensen (Overall ≥ 85).




Begrensninger og videre arbeid
- Vindusstørrelsen
K = 4er vilkårlig; et dynamisk besittelsesbasert vindu vil gi mer presise sekvenser. - Hendelser fra begge lag er inkludert i grafen, noe som skaper artefakter (Foul ↔ Free kick won er speilhendelser).
- Dataene er aggregert på tvers av fem ligaer; ligaspesifikke mønstre er skjult.
- Foreslått videre analyse: filtrer på
event_team= angripende lag, bruk sanntidsposisjonsdata (x/y) for Expected Goals (xG)-modell.