{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Classification des Micro-régions de Corse par K-NN\n",
"\n",
"Ce notebook implémente un système de classification des micro-régions corses basé sur l'algorithme des k plus proches voisins (k-NN). Cliquez sur la carte pour identifier la micro-région correspondante.\n",
"\n",
"**Fichiers nécessaires :**\n",
"- `communes-de-corse-en-corse-et-francais.csv` : Liste des communes avec coordonnées GPS\n",
"- `communes-par-territoire-de-projet-de-la-collectivite-territoriale-de-corse0.csv` : Territoires de projet par commune"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Installation des bibliothèques nécessaires\n",
"!pip install folium pandas numpy scikit-learn --quiet"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"import numpy as np\n",
"import folium\n",
"from sklearn.neighbors import KNeighborsClassifier\n",
"from IPython.display import display, HTML\n",
"import json\n",
"import re"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1. Chargement et préparation des données"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Chargement du fichier avec les coordonnées GPS\n",
"df_coords = pd.read_csv('communes-de-corse-en-corse-et-francais.csv', \n",
" sep=';', encoding='utf-8')\n",
"\n",
"print(f\"Fichier coordonnées: {len(df_coords)} communes\")\n",
"print(\"\\nPremières lignes:\")\n",
"display(df_coords.head())\n",
"print(\"\\nColonnes disponibles:\")\n",
"print(df_coords.columns.tolist())"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Chargement du fichier avec les territoires de projet\n",
"df_territoires = pd.read_csv('communes-par-territoire-de-projet-de-la-collectivite-territoriale-de-corse0.csv',\n",
" sep=';', encoding='utf-8')\n",
"\n",
"print(f\"Fichier territoires: {len(df_territoires)} communes\")\n",
"print(\"\\nPremières lignes:\")\n",
"display(df_territoires.head())\n",
"print(\"\\nTerritoires de projet (micro-régions):\")\n",
"print(sorted(df_territoires['Territoire de projet'].unique()))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. Extraction des coordonnées GPS"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def extract_coordinates(point_geo_str):\n",
" \"\"\"\n",
" Extrait latitude et longitude de la colonne Point_Geo\n",
" Format attendu: \"41.984099158, 8.798384636\"\n",
" \"\"\"\n",
" if pd.isna(point_geo_str):\n",
" return None, None\n",
" \n",
" try:\n",
" # Supprimer les espaces et split par virgule\n",
" coords = str(point_geo_str).strip().split(',')\n",
" if len(coords) == 2:\n",
" lat = float(coords[0].strip())\n",
" lon = float(coords[1].strip())\n",
" return lat, lon\n",
" except:\n",
" pass\n",
" \n",
" return None, None\n",
"\n",
"# Extraction des coordonnées\n",
"df_coords[['Latitude', 'Longitude']] = df_coords['Point_Geo'].apply(\n",
" lambda x: pd.Series(extract_coordinates(x))\n",
")\n",
"\n",
"# Vérification\n",
"print(\"Extraction des coordonnées:\")\n",
"print(f\"Communes avec coordonnées: {df_coords['Latitude'].notna().sum()}/{len(df_coords)}\")\n",
"print(\"\\nExemple:\")\n",
"display(df_coords[['Nom français', 'Latitude', 'Longitude']].head())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. Fusion des deux fichiers"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Normalisation des noms de communes pour la jointure\n",
"def normalize_commune_name(name):\n",
" \"\"\"\n",
" Normalise le nom d'une commune pour faciliter la jointure\n",
" \"\"\"\n",
" if pd.isna(name):\n",
" return ''\n",
" # Convertir en majuscules et supprimer les espaces multiples\n",
" return str(name).upper().strip()\n",
"\n",
"df_coords['Commune_norm'] = df_coords['Nom français'].apply(normalize_commune_name)\n",
"df_territoires['Commune_norm'] = df_territoires['Commune'].apply(normalize_commune_name)\n",
"\n",
"# Fusion des deux dataframes\n",
"df = pd.merge(\n",
" df_coords,\n",
" df_territoires[['Commune_norm', 'Territoire de projet']],\n",
" on='Commune_norm',\n",
" how='inner'\n",
")\n",
"\n",
"# Renommer pour cohérence\n",
"df['Commune'] = df['Nom français']\n",
"\n",
"print(f\"Fusion réussie: {len(df)} communes avec coordonnées ET territoire de projet\")\n",
"print(\"\\nAperçu des données fusionnées:\")\n",
"display(df[['Commune', 'Latitude', 'Longitude', 'Territoire de projet']].head(10))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Nettoyage: supprimer les lignes sans coordonnées\n",
"df_clean = df.dropna(subset=['Latitude', 'Longitude', 'Territoire de projet']).copy()\n",
"\n",
"print(f\"\\n✅ Données finales: {len(df_clean)} communes prêtes pour la classification\")\n",
"print(f\"\\nRépartition par micro-région:\")\n",
"print(df_clean['Territoire de projet'].value_counts().sort_index())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 4. Entraînement du modèle k-NN"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Préparation des données pour k-NN\n",
"X = df_clean[['Latitude', 'Longitude']].values\n",
"y = df_clean['Territoire de projet'].values\n",
"\n",
"# Création du modèle k-NN avec k=5 (ajustable)\n",
"k = 5\n",
"knn = KNeighborsClassifier(n_neighbors=k, weights='distance', metric='haversine')\n",
"\n",
"# Conversion des coordonnées en radians pour la distance haversine\n",
"X_rad = np.radians(X)\n",
"\n",
"# Entraînement du modèle\n",
"knn.fit(X_rad, y)\n",
"\n",
"print(f\"✅ Modèle k-NN entraîné avec k={k} voisins\")\n",
"print(f\"📊 Nombre de micro-régions: {len(np.unique(y))}\")\n",
"print(f\"\\n🗺️ Micro-régions identifiées:\")\n",
"for i, region in enumerate(sorted(np.unique(y)), 1):\n",
" count = (y == region).sum()\n",
" print(f\" {i:2d}. {region} ({count} communes)\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5. Création de la carte interactive avec Folium"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Couleurs pour chaque micro-région\n",
"microregions = sorted(df_clean['Territoire de projet'].unique())\n",
"colors = ['red', 'blue', 'green', 'purple', 'orange', 'darkred', \n",
" 'lightred', 'beige', 'darkblue', 'darkgreen', 'cadetblue', \n",
" 'darkpurple', 'pink', 'lightblue', 'lightgreen', 'gray', 'black', 'lightgray']\n",
"\n",
"color_map = {region: colors[i % len(colors)] for i, region in enumerate(microregions)}\n",
"\n",
"print(\"🎨 Carte des couleurs par micro-région:\")\n",
"for region, color in sorted(color_map.items()):\n",
" print(f\" • {region}: {color}\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Coordonnées du centre de la Corse\n",
"center_lat = df_clean['Latitude'].mean()\n",
"center_lon = df_clean['Longitude'].mean()\n",
"\n",
"print(f\"Centre de la carte: {center_lat:.4f}°N, {center_lon:.4f}°E\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 6. Carte interactive avec prédiction au clic"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Création de la carte interactive\n",
"m_interactive = folium.Map(\n",
" location=[center_lat, center_lon],\n",
" zoom_start=9,\n",
" tiles='OpenStreetMap'\n",
")\n",
"\n",
"# Ajout des marqueurs pour chaque commune\n",
"for idx, row in df_clean.iterrows():\n",
" folium.CircleMarker(\n",
" location=[row['Latitude'], row['Longitude']],\n",
" radius=3,\n",
" popup=f\"{row['Commune']}
{row['Territoire de projet']}
({row['Latitude']:.4f}, {row['Longitude']:.4f})\",\n",
" tooltip=row['Commune'],\n",
" color=color_map[row['Territoire de projet']],\n",
" fill=True,\n",
" fillColor=color_map[row['Territoire de projet']],\n",
" fillOpacity=0.7\n",
" ).add_to(m_interactive)\n",
"\n",
"# Préparer les données des communes pour JavaScript\n",
"communes_data = df_clean[['Latitude', 'Longitude', 'Commune', 'Territoire de projet']].to_dict('records')\n",
"\n",
"# JavaScript pour la prédiction k-NN au clic\n",
"click_js = f\"\"\"\n",
"\n",
"\"\"\"\n",
"\n",
"m_interactive.get_root().html.add_child(folium.Element(click_js))\n",
"\n",
"# Ajout de la légende\n",
"legend_html = '''\n",
"
🗺️ Micro-régions de Corse
\n", "'''\n", "\n", "for region, color in sorted(color_map.items()):\n", " legend_html += f'{region}
'\n", "\n", "legend_html += f'k = {k} voisins
Distance: Haversine
🖱️ Mode d'emploi
\n", "Cliquez n'importe où sur la carte pour prédire la micro-région.
\n", "• Un marqueur coloré apparaît au point cliqué
\n",
"• Les lignes pointillées montrent les k communes les plus proches
\n",
"• Le popup affiche la prédiction détaillée