Les données footballistiques représentent une source précieuse pour analyser les performances des équipes, identifier les tendances saisonnières et soutenir la prise de décision dans le sport.
Ce projet a pour objectif de construire un pipeline PySpark complet permettant d’analyser la performance des équipes saison par saison, de calculer des indicateurs clés de performance (KPI), de classer les équipes, et de stocker les résultats au format Parquet partitionné.
- Charger et préparer les données de matchs de football.
- Calculer des statistiques avancées par équipe et par saison.
- Identifier les champions de chaque saison.
- Sauvegarder les résultats sous format Parquet partitionné par saison.
- Visualiser les performances des équipes gagnantes.
- (Bonus) Intégrer le pipeline dans Databricks et créer un dashboard Power BI.
| Rôle | Besoin | Résultat attendu |
|---|---|---|
| Analyste | Visualiser un tableau clair des performances par équipe et par saison. | Table des KPI par saison. |
| Supporter | Connaître les champions de chaque saison. | Tableau ou graphique des équipes championnes. |
| Manager sportif | Disposer d’indicateurs (% victoires, buts marqués, goal diff) pour orienter la stratégie. | Dashboard Power BI ou graphiques. |
flowchart TB
%% ========================
%% 🎯 ARCHITECTURE DU PIPELINE FOOTBALL
%% ========================
%% === DÉFINITIONS DES STYLES ===
classDef load fill:#D6EAF8,stroke:#2E86C1,stroke-width:2px,color:#000,font-weight:bold; %% Bleu clair
classDef filter fill:#D1F2EB,stroke:#117864,stroke-width:2px,color:#000,font-weight:bold; %% Vert clair
classDef agg fill:#FDEBD0,stroke:#CA6F1E,stroke-width:2px,color:#000,font-weight:bold; %% Orange clair
classDef kpi fill:#FADBD8,stroke:#C0392B,stroke-width:2px,color:#000,font-weight:bold; %% Rouge clair
classDef rank fill:#E8DAEF,stroke:#7D3C98,stroke-width:2px,color:#000,font-weight:bold; %% Violet
classDef save fill:#FCF3CF,stroke:#B7950B,stroke-width:2px,color:#000,font-weight:bold; %% Jaune clair
classDef vis fill:#D5F5E3,stroke:#27AE60,stroke-width:2px,color:#000,font-weight:bold; %% Vert tendre
%% === 1️⃣ CHARGEMENT & PRÉPARATION ===
subgraph LOAD["📥 Chargement & préparation des données"]
LOAD1(["📂 Import CSV dans DataFrame PySpark"])
LOAD2(["🧹 Nettoyage & renommage des colonnes (footballcolumnsdocumentation.pdf)"])
LOAD3(["➕ Création colonnes supplémentaires : HomeTeamWin, AwayTeamWin, GameTie"])
end
class LOAD1,LOAD2,LOAD3 load;
%% === 2️⃣ FILTRAGE ===
subgraph FILTER["🔎 Filtrage des données"]
FILTER1(["⚽ Conserver uniquement Bundesliga (Div = D1)"])
FILTER2(["📅 Période : 2000 à 2015"])
end
class FILTER1,FILTER2 filter;
%% === 3️⃣ AGRÉGATIONS ===
subgraph AGG["🧮 Agrégations"]
AGG1(["🏠 df_home_matches : statistiques domicile"])
AGG2(["🚗 df_away_matches : statistiques extérieur"])
AGG3(["🔗 Jointure → df_merged"])
end
class AGG1,AGG2,AGG3 agg;
%% === 4️⃣ KPI ===
subgraph KPI["📊 Calcul des KPI"]
KPI1(["⚡ Colonnes totales : GoalsScored, GoalsAgainst, Win, Loss, Tie"])
KPI2(["📈 Colonnes avancées : GoalDifferentials, WinPercentage, GoalsPerGame, GoalsAgainstPerGame"])
end
class KPI1,KPI2 kpi;
%% === 5️⃣ CLASSEMENT ===
subgraph RANK["🏆 Classement des équipes"]
RANK1(["📊 Window Functions : classement par WinPercentage, GoalDifferentials"])
RANK2(["🥇 Extraction du champion : TeamPosition = 1"])
end
class RANK1,RANK2 rank;
%% === 6️⃣ SAUVEGARDE ===
subgraph SAVE["💾 Sauvegarde optimisée"]
SAVE1(["🗂 football_stats_partitioned : toutes les équipes, partitionné par saison"])
SAVE2(["🏅 football_top_teams : champions uniquement"])
end
class SAVE1,SAVE2 save;
%% === 7️⃣ VISUALISATION ===
subgraph VIS["📉 Visualisation & Reporting"]
VIS1(["📊 Graphiques % victoires des champions"])
VIS2(["⚽ Nombre de buts marqués"])
VIS3(["📈 GoalDifferentials par saison"])
VIS4(["🧰 Outils : Pandas / Matplotlib / Power BI"])
end
class VIS1,VIS2,VIS3,VIS4 vis;
%% === 🔄 FLUX DU PIPELINE ===
LOAD1 --> LOAD2 --> LOAD3 --> FILTER1 --> FILTER2 --> AGG1 --> AGG2 --> AGG3
AGG3 --> KPI1 --> KPI2 --> RANK1 --> RANK2 --> SAVE1 --> SAVE2 --> VIS1
SAVE2 --> VIS2
SAVE2 --> VIS3
VIS1 --> VIS4
VIS2 --> VIS4
VIS3 --> VIS4
-
Chargement et préparation des données
- Import du fichier CSV dans un DataFrame PySpark.
- Nettoyage et renommage des colonnes selon
footballcolumnsdocumentation.pdf.
-
Création de colonnes supplémentaires
- Colonnes indicatrices :
HomeTeamWin,AwayTeamWin,GameTie.
- Colonnes indicatrices :
-
Filtrage des données
- Conservation uniquement de la Bundesliga (Div = D1).
- Période : 2000 à 2015.
-
Agrégations
df_home_matches: statistiques à domicile.df_away_matches: statistiques à l’extérieur.- Jointure →
df_merged.
-
Calcul des KPI
- Colonnes totales :
GoalsScored,GoalsAgainst,Win,Loss,Tie. - Colonnes avancées :
GoalDifferentials,WinPercentage,GoalsPerGame,GoalsAgainstPerGame.
- Colonnes totales :
-
Classement des équipes
- Utilisation des Window Functions pour classer les équipes selon :
WinPercentageGoalDifferentials
- Extraction du champion :
TeamPosition = 1.
- Utilisation des Window Functions pour classer les équipes selon :
-
Sauvegarde optimisée
football_stats_partitioned: toutes les équipes, partitionné par saison.football_top_teams: champions uniquement.
-
Visualisation (Pandas / Matplotlib / Power BI)
- Graphiques :
- % de victoires des champions.
- Nombre de buts marqués.
- GoalDifferentials par saison.
- Graphiques :
football-performance-pipeline/
│
├── data/
│ ├── raw/ # Données CSV brutes
│ │ └── football_matches.csv
│ ├── processed/ # Données transformées (parquet)
│ │ ├── football_stats_partitioned/
│ │ └── football_top_teams/
│ └── tests/ # Jeux de données miniatures pour tests
│ └── sample_data.csv
│
├── src/
│ ├── __init__.py
│ ├── config/
│ │ └── spark_config.py # Configuration SparkSession
│ ├── ingestion/
│ │ └── load_data.py # Chargement CSV → DataFrame
│ ├── transformation/
│ │ ├── prepare_columns.py # Nettoyage, renommage
│ │ ├── indicators.py # Colonnes indicatrices (HomeTeamWin, etc.)
│ │ ├── filter_data.py # Filtrage D1 + saisons 2000–2015
│ │ ├── aggregations.py # GroupBy domicile / extérieur
│ │ ├── merge_data.py # Fusion home/away
│ │ ├── metrics.py # Colonnes synthétiques + KPIs
│ │ └── ranking.py # Classement via Window Functions
│ ├── export/
│ │ └── save_parquet.py # Sauvegarde des Parquet
│ ├── visualization/
│ │ └── charts.py # Graphiques Matplotlib / Seaborn
│ └── pipeline.py # Script principal orchestrant le pipeline
│
├── tests/
│ ├── __init__.py
│ ├── test_ingestion.py # Tests du chargement
│ ├── test_transformation.py # Tests transformations & indicateurs
│ ├── test_metrics.py # Tests des calculs de KPI
│ ├── test_ranking.py # Tests de classement
│ └── test_export.py # Tests du format Parquet
│
├── notebooks/
│ ├── pipeline_exploration.ipynb # Exploration initiale
│ └── debug_visuals.ipynb # Debug + visualisation
│
├── logs/
│ └── pipeline.log # Logs détaillés d’exécution
│
├── requirements.txt # Dépendances (PySpark, pytest, matplotlib...)
├── README.md # Documentation du projet
└── .gitignore # Fichiers à ignorer (parquet, cache, logs)
| KPI | Description | Formule |
|---|---|---|
| WinPercentage | Pourcentage de victoires | Wins / (Wins + Losses + Ties) |
| GoalsPerGame | Moyenne de buts marqués par match | GoalsScored / GamesPlayed |
| GoalsAgainstPerGame | Moyenne de buts encaissés par match | GoalsAgainst / GamesPlayed |
| GoalDifferentials | Différence de buts | GoalsScored - GoalsAgainst |
| Catégorie | Outils |
|---|---|
| Langage principal | Python 3.10+ |
| Traitement distribué | Apache Spark / PySpark |
| Stockage optimisé | Parquet partitionné |
| Exploration / Visualisation | Pandas, Matplotlib, Power BI |
| Environnement d’exécution | Google Colab, Databricks Community Edition |
| Gestion de version | GitHub |
- PySpark DataFrame API : pour les transformations distribuées.
- GroupBy & Aggregations : statistiques par équipe et saison.
- Window Functions : classement par saison.
- Parquet partitionné : stockage optimisé pour la lecture sélective.
- Matplotlib / Power BI : visualisation de la performance.
!pip install pyspark
from pyspark.sql import SparkSession
spark = SparkSession.builder.appName("FootballAnalysis").getOrCreate()
df = spark.read.csv("/content/football_matches.csv", header=True, inferSchema=True)df_final.write.mode("overwrite").partitionBy("Season").parquet("/content/football_stats_partitioned")df = spark.read.parquet("/content/football_stats_partitioned")
df.printSchema()football_stats_partitioned: contient toutes les équipes, partitionné par saison.football_top_teams: contient uniquement les champions de chaque saison.
- Pourcentage de victoires des champions
- Nombre de buts marqués par saison
- GoalDifferentials (différence de buts) par saison
- Recréer le pipeline dans un notebook Databricks Community Edition (CE).
- Comparer les performances entre Google Colab et Databricks.
- Utiliser la commande :
display(df)
-
Importer les fichiers
.parquetgénérés depuis le dossier :/data -
Créer un tableau de bord interactif comprenant :
-
Pourcentage de victoires (%Win)
-
Nombre de buts marqués (Goals)
-
Différence de buts (GoalDiff)
-
Ajouter des filtres dynamiques :
-
Par saison
-
Par équipe
- Apache Spark — Documentation officielle
- Databricks Community Edition
- Power BI — Importer des fichiers Parquet
- Football Data Source — Kaggle
- Football Data Europe
Salim Majide
🎓 Ingénieur Big Data & Cloud Computing (ENSET Mohammedia)
💼 Projet Data Engineering - PySpark
📧 Contact : LinkedIn
- Notebook Google Colab ou Databricks commenté
- Datasets Parquet :
/data/football_stats_partitioned/data/football_top_teams - Graphiques : Win%, Goals, GoalDiff
- Lien GitHub : Notebook, Datasets Parquet, Visualisations, README
Ce projet illustre la mise en œuvre complète d’un pipeline de données PySpark, depuis la préparation jusqu’à la visualisation, en appliquant les bonnes pratiques d’ingénierie de données, ainsi que les principes d’optimisation des performances et de déploiement sur Databricks et Power BI.