{
"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."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Installation des bibliothèques nécessaires\n",
"!pip install folium pandas numpy scikit-learn geopy --quiet"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"import numpy as np\n",
"import folium\n",
"from folium import plugins\n",
"from sklearn.neighbors import KNeighborsClassifier\n",
"from geopy.geocoders import Nominatim\n",
"from geopy.extra.rate_limiter import RateLimiter\n",
"import time\n",
"from IPython.display import display, HTML\n",
"import json"
]
},
{
"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 CSV\n",
"df = pd.read_csv('communes-par-territoire-de-projet-de-la-collectivite-territoriale-de-corse0.csv', \n",
" sep=';', encoding='utf-8')\n",
"\n",
"print(f\"Nombre de communes: {len(df)}\")\n",
"print(\"\\nPremières lignes:\")\n",
"display(df.head())\n",
"print(\"\\nTerritoires de projet (micro-régions):\")\n",
"print(df['Territoire de projet'].unique())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. Géocodage des communes\n",
"\n",
"Si le fichier ne contient pas déjà les coordonnées GPS, nous les récupérons via géocodage."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Fonction pour obtenir les coordonnées GPS d'une commune\n",
"def geocode_commune(commune, departement, code_postal):\n",
" \"\"\"\n",
" Géocode une commune corse pour obtenir ses coordonnées GPS\n",
" \"\"\"\n",
" geolocator = Nominatim(user_agent=\"corse_knn_classifier\")\n",
" \n",
" try:\n",
" # Essai avec le nom de la commune et Corse\n",
" query = f\"{commune}, Corse, France\"\n",
" location = geolocator.geocode(query, timeout=10)\n",
" \n",
" if location:\n",
" return location.latitude, location.longitude\n",
" \n",
" # Essai avec le code postal\n",
" query = f\"{commune}, {code_postal}, France\"\n",
" location = geolocator.geocode(query, timeout=10)\n",
" \n",
" if location:\n",
" return location.latitude, location.longitude\n",
" \n",
" except Exception as e:\n",
" print(f\"Erreur pour {commune}: {e}\")\n",
" \n",
" return None, None\n",
"\n",
"# Vérifier si les colonnes GPS existent déjà\n",
"if 'Latitude' not in df.columns or 'Longitude' not in df.columns:\n",
" print(\"Géocodage des communes en cours... (cela peut prendre quelques minutes)\")\n",
" \n",
" # Géocodage avec rate limiting pour respecter les limites de l'API\n",
" latitudes = []\n",
" longitudes = []\n",
" \n",
" for idx, row in df.iterrows():\n",
" lat, lon = geocode_commune(row['Commune'], row['Département'], row['Code Postal'])\n",
" latitudes.append(lat)\n",
" longitudes.append(lon)\n",
" \n",
" # Affichage de la progression\n",
" if (idx + 1) % 10 == 0:\n",
" print(f\"Progression: {idx + 1}/{len(df)} communes géocodées\")\n",
" \n",
" # Pause pour respecter les limites de l'API\n",
" time.sleep(1.5)\n",
" \n",
" df['Latitude'] = latitudes\n",
" df['Longitude'] = longitudes\n",
" \n",
" # Sauvegarde du dataframe avec coordonnées\n",
" df.to_csv('communes_corse_avec_gps.csv', sep=';', index=False, encoding='utf-8')\n",
" print(\"\\nGéocodage terminé et sauvegardé dans 'communes_corse_avec_gps.csv'\")\n",
"else:\n",
" print(\"Les coordonnées GPS sont déjà présentes dans le fichier.\")\n",
"\n",
"# Supprimer les lignes sans coordonnées\n",
"df_clean = df.dropna(subset=['Latitude', 'Longitude']).copy()\n",
"print(f\"\\nCommunes avec coordonnées GPS: {len(df_clean)}/{len(df)}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. 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\"Micro-régions: {sorted(np.unique(y))}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 4. 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 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",
"# Création de la carte\n",
"m = 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']}\",\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)\n",
"\n",
"# Ajout d'une 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 += '🖱️ Instructions:
\n", "Cliquez n'importe où sur la carte pour prédire la micro-région à partir de l'algorithme k-NN.
\n", "Les lignes pointillées montrent les k plus proches communes utilisées pour la prédiction.
\n", "