knnCorsica/activite2/classification_corse_knn_V2.ipynb

688 lines
25 KiB
Text
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"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\"<b>{row['Commune']}</b><br>{row['Territoire de projet']}<br><small>({row['Latitude']:.4f}, {row['Longitude']:.4f})</small>\",\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",
"<script>\n",
"// Données des communes\n",
"var communesData = {json.dumps(communes_data)};\n",
"\n",
"// Carte des couleurs\n",
"var colorMap = {json.dumps(color_map)};\n",
"\n",
"// Fonction pour calculer la distance haversine\n",
"function haversineDistance(lat1, lon1, lat2, lon2) {{\n",
" const R = 6371; // Rayon de la Terre en km\n",
" const dLat = (lat2 - lat1) * Math.PI / 180;\n",
" const dLon = (lon2 - lon1) * Math.PI / 180;\n",
" const a = Math.sin(dLat/2) * Math.sin(dLat/2) +\n",
" Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *\n",
" Math.sin(dLon/2) * Math.sin(dLon/2);\n",
" const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));\n",
" return R * c;\n",
"}}\n",
"\n",
"// Fonction k-NN\n",
"function predictRegion(lat, lon, k) {{\n",
" // Calculer les distances\n",
" var distances = communesData.map(function(commune) {{\n",
" return {{\n",
" distance: haversineDistance(lat, lon, commune.Latitude, commune.Longitude),\n",
" region: commune['Territoire de projet'],\n",
" commune: commune.Commune\n",
" }};\n",
" }});\n",
" \n",
" // Trier par distance\n",
" distances.sort((a, b) => a.distance - b.distance);\n",
" \n",
" // Prendre les k plus proches\n",
" var kNearest = distances.slice(0, k);\n",
" \n",
" // Vote pondéré par l'inverse de la distance\n",
" var votes = {{}};\n",
" kNearest.forEach(function(neighbor) {{\n",
" var weight = 1 / (neighbor.distance + 0.001); // +0.001 pour éviter division par 0\n",
" if (votes[neighbor.region]) {{\n",
" votes[neighbor.region] += weight;\n",
" }} else {{\n",
" votes[neighbor.region] = weight;\n",
" }}\n",
" }});\n",
" \n",
" // Trouver la région gagnante\n",
" var maxVote = 0;\n",
" var predictedRegion = '';\n",
" for (var region in votes) {{\n",
" if (votes[region] > maxVote) {{\n",
" maxVote = votes[region];\n",
" predictedRegion = region;\n",
" }}\n",
" }}\n",
" \n",
" return {{\n",
" region: predictedRegion,\n",
" neighbors: kNearest\n",
" }};\n",
"}}\n",
"\n",
"// Variable pour stocker le marqueur de prédiction\n",
"var predictionMarker = null;\n",
"var neighborLines = [];\n",
"\n",
"// Attendre que la carte soit chargée\n",
"setTimeout(function() {{\n",
" var maps = document.querySelectorAll('.folium-map');\n",
" if (maps.length > 0) {{\n",
" var mapElement = maps[maps.length - 1];\n",
" var leafletMap = mapElement._leaflet_map;\n",
" \n",
" if (leafletMap) {{\n",
" leafletMap.on('click', function(e) {{\n",
" var lat = e.latlng.lat;\n",
" var lon = e.latlng.lng;\n",
" \n",
" // Prédiction avec k={k}\n",
" var result = predictRegion(lat, lon, {k});\n",
" \n",
" // Supprimer l'ancien marqueur et lignes\n",
" if (predictionMarker) {{\n",
" leafletMap.removeLayer(predictionMarker);\n",
" }}\n",
" neighborLines.forEach(function(line) {{\n",
" leafletMap.removeLayer(line);\n",
" }});\n",
" neighborLines = [];\n",
" \n",
" // Créer le popup avec informations détaillées\n",
" var popupContent = '<div style=\"min-width: 200px;\">' +\n",
" '<h4 style=\"margin: 5px 0; color: ' + colorMap[result.region] + ';\">🎯 ' + result.region + '</h4>' +\n",
" '<p style=\"margin: 5px 0; font-size: 11px;\"><b>Coordonnées cliquées:</b><br>' + \n",
" 'Lat: ' + lat.toFixed(5) + '°<br>Lon: ' + lon.toFixed(5) + '°</p>' +\n",
" '<hr style=\"margin: 5px 0;\">' +\n",
" '<p style=\"margin: 5px 0; font-size: 11px;\"><b>{k} plus proches communes:</b></p>' +\n",
" '<ul style=\"margin: 5px 0; padding-left: 20px; font-size: 10px;\">';\n",
" \n",
" result.neighbors.forEach(function(neighbor, i) {{\n",
" popupContent += '<li><b>' + neighbor.commune + '</b> (' + neighbor.distance.toFixed(2) + ' km)</li>';\n",
" }});\n",
" \n",
" popupContent += '</ul></div>';\n",
" \n",
" // Ajouter le nouveau marqueur\n",
" predictionMarker = L.marker([lat, lon], {{\n",
" icon: L.divIcon({{\n",
" className: 'prediction-marker',\n",
" html: '<div style=\"background-color: ' + colorMap[result.region] + \n",
" '; width: 20px; height: 20px; border-radius: 50%; ' +\n",
" 'border: 3px solid white; box-shadow: 0 0 10px rgba(0,0,0,0.5);\"></div>',\n",
" iconSize: [20, 20]\n",
" }})\n",
" }}).addTo(leafletMap);\n",
" \n",
" predictionMarker.bindPopup(popupContent, {{maxWidth: 300}}).openPopup();\n",
" \n",
" // Ajouter des lignes vers les k plus proches voisins\n",
" result.neighbors.forEach(function(neighbor) {{\n",
" var commune = communesData.find(c => c.Commune === neighbor.commune);\n",
" if (commune) {{\n",
" var line = L.polyline(\n",
" [[lat, lon], [commune.Latitude, commune.Longitude]],\n",
" {{\n",
" color: 'gray',\n",
" weight: 1,\n",
" opacity: 0.5,\n",
" dashArray: '5, 5'\n",
" }}\n",
" ).addTo(leafletMap);\n",
" neighborLines.push(line);\n",
" }}\n",
" }});\n",
" }});\n",
" \n",
" console.log('✅ Gestionnaire de clic k-NN activé');\n",
" console.log('📊 ' + communesData.length + ' communes chargées');\n",
" }}\n",
" }}\n",
"}}, 1000);\n",
"</script>\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",
"<div style=\"position: fixed; \n",
" top: 10px; right: 10px; width: 250px; max-height: 85vh; overflow-y: auto;\n",
" background-color: white; border:2px solid grey; z-index:9999; border-radius: 5px;\n",
" font-size:12px; padding: 10px; box-shadow: 0 0 15px rgba(0,0,0,0.2);\">\n",
"<p style=\"margin-bottom: 8px; font-weight: bold; font-size: 14px;\">🗺️ Micro-régions de Corse</p>\n",
"'''\n",
"\n",
"for region, color in sorted(color_map.items()):\n",
" legend_html += f'<p style=\"margin: 3px 0;\"><i class=\"fa fa-circle\" style=\"color:{color}\"></i> {region}</p>'\n",
"\n",
"legend_html += f'<hr style=\"margin: 8px 0;\"><p style=\"margin: 3px 0; font-size: 11px; color: #666;\">k = {k} voisins<br>Distance: Haversine</p></div>'\n",
"\n",
"m_interactive.get_root().html.add_child(folium.Element(legend_html))\n",
"\n",
"# Ajout d'instructions\n",
"instructions_html = '''\n",
"<div style=\"position: fixed; \n",
" bottom: 10px; left: 10px; width: 320px; \n",
" background-color: white; border:2px solid grey; z-index:9999; border-radius: 5px;\n",
" font-size:13px; padding: 12px; box-shadow: 0 0 15px rgba(0,0,0,0.2);\">\n",
"<p style=\"margin: 0 0 8px 0; font-weight: bold;\">🖱️ Mode d'emploi</p>\n",
"<p style=\"margin: 5px 0; line-height: 1.4;\"><b>Cliquez</b> n'importe où sur la carte pour prédire la micro-région.</p>\n",
"<p style=\"margin: 5px 0; line-height: 1.4; font-size: 11px;\">• Un marqueur coloré apparaît au point cliqué<br>\n",
"• Les lignes pointillées montrent les k communes les plus proches<br>\n",
"• Le popup affiche la prédiction détaillée</p>\n",
"</div>\n",
"'''\n",
"\n",
"m_interactive.get_root().html.add_child(folium.Element(instructions_html))\n",
"\n",
"print(\"\\n✅ Carte interactive créée avec succès!\")\n",
"print(f\"\\n🖱 Cliquez sur n'importe quel point de la carte pour prédire sa micro-région avec k={k} voisins.\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Affichage de la carte interactive\n",
"m_interactive"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 7. Sauvegarde de la carte"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Sauvegarder la carte interactive\n",
"m_interactive.save('carte_corse_knn_interactive.html')\n",
"print(\"✅ Carte sauvegardée dans 'carte_corse_knn_interactive.html'\")\n",
"print(\"📁 Vous pouvez ouvrir ce fichier dans un navigateur pour une utilisation autonome.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 8. Test de la prédiction (optionnel)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Fonction pour tester la prédiction sur des coordonnées spécifiques\n",
"def predict_region(lat, lon, k_value=5):\n",
" \"\"\"\n",
" Prédit la micro-région pour des coordonnées données\n",
" \"\"\"\n",
" # Conversion en radians\n",
" coords_rad = np.radians([[lat, lon]])\n",
" \n",
" # Prédiction\n",
" prediction = knn.predict(coords_rad)[0]\n",
" \n",
" # Trouver les k plus proches voisins\n",
" distances, indices = knn.kneighbors(coords_rad)\n",
" \n",
" # Convertir les distances de radians en km\n",
" distances_km = distances[0] * 6371 # Rayon de la Terre en km\n",
" \n",
" print(f\"\\n📍 Coordonnées: {lat:.5f}°N, {lon:.5f}°E\")\n",
" print(f\"🎯 Micro-région prédite: {prediction}\")\n",
" print(f\"\\n{k_value} plus proches communes:\")\n",
" \n",
" for i, idx in enumerate(indices[0]):\n",
" commune_info = df_clean.iloc[idx]\n",
" print(f\" {i+1}. {commune_info['Commune']:30s} ({commune_info['Territoire de projet']:30s}) - {distances_km[i]:6.2f} km\")\n",
" \n",
" return prediction\n",
"\n",
"# Exemples de test\n",
"print(\"=\" * 100)\n",
"print(\"TESTS DE PRÉDICTION k-NN\")\n",
"print(\"=\" * 100)\n",
"\n",
"# Test 1: Centre approximatif de la Corse (vers Corte)\n",
"print(\"\\n🔍 Test 1: Centre de la Corse\")\n",
"predict_region(42.15, 9.15, k)\n",
"\n",
"# Test 2: Nord de la Corse (Balagne/Bastia)\n",
"print(\"\\n🔍 Test 2: Nord de la Corse\")\n",
"predict_region(42.55, 8.85, k)\n",
"\n",
"# Test 3: Sud de la Corse (vers Porto-Vecchio)\n",
"print(\"\\n🔍 Test 3: Sud de la Corse\")\n",
"predict_region(41.65, 9.15, k)\n",
"\n",
"# Test 4: Ouest (vers Ajaccio)\n",
"print(\"\\n🔍 Test 4: Ouest de la Corse (Ajaccio)\")\n",
"predict_region(41.93, 8.74, k)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 9. Analyse de performance (optionnel)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Évaluation de la cohérence du modèle (cross-validation)\n",
"from sklearn.model_selection import cross_val_score\n",
"\n",
"# Test avec différentes valeurs de k\n",
"k_values = [3, 5, 7, 9, 11, 15]\n",
"scores = []\n",
"\n",
"print(\"📊 Évaluation de la précision pour différentes valeurs de k:\\n\")\n",
"print(f\"{'k':<5} {'Précision moyenne':<20} {'Écart-type':<15}\")\n",
"print(\"-\" * 50)\n",
"\n",
"for k_val in k_values:\n",
" knn_temp = KNeighborsClassifier(n_neighbors=k_val, weights='distance', metric='haversine')\n",
" cv_scores = cross_val_score(knn_temp, X_rad, y, cv=5)\n",
" mean_score = cv_scores.mean()\n",
" std_score = cv_scores.std()\n",
" scores.append(mean_score)\n",
" print(f\"{k_val:<5} {mean_score:.4f} ({mean_score*100:5.2f}%) ± {std_score:.4f}\")\n",
"\n",
"best_k = k_values[scores.index(max(scores))]\n",
"best_score = max(scores)\n",
"print(\"\\n\" + \"=\" * 50)\n",
"print(f\"✨ Meilleure valeur de k: {best_k} (précision: {best_score:.4f} / {best_score*100:.2f}%)\")\n",
"print(\"=\" * 50)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 10. Statistiques par micro-région"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Statistiques descriptives par micro-région\n",
"print(\"📈 STATISTIQUES PAR MICRO-RÉGION\\n\")\n",
"print(f\"{'Micro-région':<35} {'Nb communes':<15} {'% du total'}\")\n",
"print(\"=\" * 65)\n",
"\n",
"total_communes = len(df_clean)\n",
"stats = df_clean['Territoire de projet'].value_counts().sort_index()\n",
"\n",
"for region, count in stats.items():\n",
" pct = (count / total_communes) * 100\n",
" print(f\"{region:<35} {count:<15} {pct:>5.1f}%\")\n",
"\n",
"print(\"=\" * 65)\n",
"print(f\"{'TOTAL':<35} {total_communes:<15} 100.0%\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Conclusion\n",
"\n",
"✅ **Notebook k-NN Corse - Résumé**\n",
"\n",
"Ce notebook implémente un classificateur k-NN pour les micro-régions de Corse avec:\n",
"1. ✅ Chargement des données depuis 2 fichiers CSV (coordonnées + territoires)\n",
"2. ✅ Extraction automatique des coordonnées GPS depuis la colonne Point_Geo\n",
"3. ✅ Fusion intelligente des deux sources de données\n",
"4. ✅ Entraînement d'un modèle k-NN avec distance haversine\n",
"5. ✅ Carte interactive Folium avec prédiction au clic\n",
"6. ✅ Visualisation des k plus proches voisins\n",
"7. ✅ Tests de performance et validation\n",
"8. ✅ Export HTML pour utilisation autonome\n",
"\n",
"**🖱️ Utilisation:**\n",
"- Cliquez n'importe où sur la carte\n",
"- Un marqueur coloré apparaît avec la micro-région prédite\n",
"- Des lignes pointillées montrent les k communes les plus proches\n",
"- Un popup détaille la prédiction et les voisins\n",
"\n",
"**📁 Fichier exporté:** `carte_corse_knn_interactive.html`\n",
"\n",
"La carte HTML peut être ouverte dans n'importe quel navigateur pour une utilisation autonome!"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.0"
}
},
"nbformat": 4,
"nbformat_minor": 4
}