Sz
Sıfır Gecikme
veri bilimi · türkçe
Tümüİnteraktif📖Rehber🛠Araç📊Vaka💼Kariyer🐍Playground📚Öğren
Hakkımda
Ana sayfavaka çalışması

Süper Lig'de xG analizi: gol mü şans mı?

2023/24 sezonu · 12 dakika okuma · Python + pandas + mplsoccer

Mauro Icardi 2023/24 sezonunda 25 golle gol krallığını aldı. Peki bu goller gerçekten Icardi'nin kalitesini mi yansıtıyor, yoksa şanslı pozisyonlar mı? xG (Expected Goals) tam olarak bu soruyu cevaplar.

xG, bir şutun gole dönüşme olasılığını 0 ile 1 arasında ifade eder. Ceza sahasının ortasından yapılan kafa vuruşu ~0.7 xG taşır. Uzaktan sert bir şut ise ~0.03. Sezon sonunda bir oyuncunun toplam xG'si ile attığı gol sayısını karşılaştırmak, gerçek katkısını ortaya koyar.

Gol > xG: oyuncu şansını iyi kullanıyor veya bitişi güçlü.
Gol < xG: şut kalitesine rağmen gole çevirememiş, ya şanssız ya da bitişi zayıf.

Veri nereden geliyor?

xG verisi için en yaygın açık kaynak StatsBomb ve Understat'tır. Python ile çekmek için:

import requests
import pandas as pd

# Understat API — ücretsiz, kayıt gerektirmez
# Süper Lig 2023/24 oyuncu istatistikleri
url = "https://understat.com/league/Super_Lig/2023"

# understatapi kütüphanesi ile daha kolay
# pip install understatapi
from understatapi import UnderstatClient

async def get_player_stats():
    async with UnderstatClient() as understat:
        players = await understat.league(league="Super_Lig").get_player_data(
            season="2023"
        )
    return pd.DataFrame(players)

import asyncio
df = asyncio.run(get_player_stats())
print(df.columns.tolist())
# ['id', 'player_name', 'games', 'time', 'goals', 'xG',
#  'assists', 'xA', 'shots', 'key_passes', 'yellow', 'red']

xG vs Gerçek Gol — Kim Şanslı, Kim Şanssız?

2023/24 Süper Lig sezonundan öne çıkan veriler. Her oyuncunun beklenen golü (xG) ile attığı gerçek gol sayısını karşılaştıralım:

# Veriyi temizle ve analiz et
df['goals'] = pd.to_numeric(df['goals'])
df['xG'] = pd.to_numeric(df['xG'])
df['xG_diff'] = df['goals'] - df['xG']  # pozitif = beklentinin üstünde

# Minimum 5 maç oynamış forveti filtrele
forvetler = df[
    (df['games'] >= 5) &
    (df['goals'] >= 3)
].copy()

# En çok "beklentiyi aşan" oyuncular
asanlar = forvetler.nlargest(10, 'xG_diff')[
    ['player_name', 'goals', 'xG', 'xG_diff', 'shots']
]
print(asanlar.to_string(index=False))

# Gerçek gol / xG oranı (bitiricilik)
forvetler['bitis_orani'] = forvetler['goals'] / forvetler['xG']
print(forvetler.nlargest(5, 'bitis_orani')[['player_name','bitis_orani']])

2023/24 Sezonu Öne Çıkan Bulgular

Transfermarkt ve Understat verilerine göre sezonun dikkat çekici xG bulguları:

Takım Bazında xG Analizi

Bireysel değil takım xG'si, hücum sisteminin ne kadar kaliteli pozisyon ürettiğini gösterir. xGF (For) − xGA (Against) farkı ise gerçek güç göstergesi.

# Takım bazında xG analizi
async def get_team_stats():
    async with UnderstatClient() as understat:
        teams = await understat.league(league="Super_Lig").get_team_data(
            season="2023"
        )
    return teams

# xGF - xGA = net xG farkı
takim_df['xG_net'] = takim_df['xGF'] - takim_df['xGA']

# Gerçek puan vs xG bazlı beklenen puan karşılaştırması
takim_df['puan_farki'] = takim_df['gercek_puan'] - takim_df['beklenen_puan']

# Puan farkı pozitif = şanslı takım
# Puan farkı negatif = hak ettiğinden az puan alan takım
print(takim_df.sort_values('puan_farki', ascending=False)[
    ['takim', 'gercek_puan', 'beklenen_puan', 'puan_farki']
])

Şut Haritası: Pozisyon Kalitesi

xG analizinin en görsel hali şut haritasıdır. Her şutun konumu ve xG değeri birlikte gösterilir. mplsoccerkütüphanesi Python'da bunu çok kolay yapıyor:

from mplsoccer import Pitch
import matplotlib.pyplot as plt
import numpy as np

# Pitch çiz
pitch = Pitch(pitch_type='statsbomb', pitch_color='#1a2a1a',
              line_color='white', line_alpha=0.5)
fig, ax = pitch.draw(figsize=(12, 8))

# Şutları çiz — boyut xG, renk gol/gol yok
for _, sut in oyuncu_sutlari.iterrows():
    renk = '#FFD700' if sut['sonuc'] == 'Goal' else '#ffffff'
    pitch.scatter(
        sut['x'], sut['y'],
        s=sut['xG'] * 1000,   # boyut = xG büyüklüğü
        c=renk, alpha=0.6, ax=ax
    )

plt.title(f"{oyuncu_adi} — 2023/24 Şut Haritası", color='white', fontsize=14)
plt.savefig('sut_haritasi.png', dpi=150, bbox_inches='tight',
            facecolor='#1a2a1a')

xG Neden Mükemmel Değil?

Her metrik gibi xG'nin de sınırları var:

Veriyi Sen de Çek

Kendi analizini yapmak istersen açık kaynak alternatifleri:

# Ücretsiz veri kaynakları

# 1. Understat — Avrupa ligleri + Süper Lig
# pip install understatapi

# 2. StatsBomb açık veri (bazı ligler ücretsiz)
# pip install statsbombpy
from statsbombpy import sb
comp = sb.competitions()  # mevcut ligleri gör

# 3. FBref üzerinden manuel scraping
import requests
from bs4 import BeautifulSoup

url = "https://fbref.com/en/comps/26/Super-Lig-Stats"
r = requests.get(url, headers={'User-Agent': 'Mozilla/5.0'})
soup = BeautifulSoup(r.text, 'html.parser')

# 4. Soccerway API (gayri resmi)
# 5. Fotmob scraping (dikkatli kullan)

Futbol analitiği artık kulüplerin teknik direktörlerine rapor sunduğu bir alan. Türkiye'de bu alanda çalışan analist sayısı hâlâ çok az. Veri bilimi + futbol tutkusu = ciddi bir kariyer fırsatı.

3 Ana Bulgu

Sıradaki vaka çalışmasında BIST momentum analizi: Türk borsasında basit bir momentum stratejisi gerçekten işe yarıyor mu?

💬 Yorumlar