24. Carte de densité#
L’enjeu de cet exercice est de parvenir à réaliser une carte de France affichant les densités de population enregistré durant les derniers recensements. Pour cela, nous avons récupéré le fichier insee_rp_hist_1968.csv
qui contient les colonnes suivantes :
codgeo
est l’indentifiant unique d’une ville ;libgeo
est le libélé d’une ville ;an
est l’année du recensement ;dens_pop
est la densité de population.
Pour afficher ces information sur une carte, il nous manque les coordonnées de chaque ville. Par chance, nous avons déjà le fichier communes_2021.csv
qui complète ces informations. Il contient les colonnes suivantes.
Geocode
est l’identifiant unique d’une ville ;nom
est le libélé d’une ville ;latitude
etlongitude
sont les coordonnées ;population
est la population en 2021.
Voici comment nous allons procédé.
Nous lirons les informations contenues dans le fichier
communes_2021.csv
et les stocker dans un dictionnaire.Nous lirons celles du fichier
insee_rp_hist_1968.csv
et nous les stockerons dans un autre dictiionnaire.Nous fusionnerons les informations des deux dictionnaires.
Enfin nous créerons une heatmap avec folium.
24.1. Lecture du fichier des communes#
Exercice : Écrivez une fonction read_city_file
qui prend en paramètre le chemin vers le fichier csv communes_2021.csv
et renvoie un dictionnaire de la forme suivante. Il associe à un geode donnée, les informations concernant la ville, à savoir : son nom et ses coordonnées. Notons que les coordonnées sont converties en nombre à virgule.
{'64001': {'nom': 'Aast',
'latitude': 43.291192630916704,
'longitude': -0.08172502738117142},
'55001': {'nom': 'Abainville',
'latitude': 48.53272044504441,
'longitude': 5.51487324547426},
'60001': {'nom': 'Abancourt',
'latitude': 49.965002813144096,
'longitude': 2.488730102972196},
...
def read_city_file(f):
pass
24.2. Lecture du fichier de densité#
Lisons maintenant les données contenues dans le fichier insee_rp_hist_1968.csv
. Nous souhaitons les stocker dans un dictionnaire ayant la forme suivante. Il associe à un geode donnée, les informations concernant les recesement. Donc pour une géocode donnée, le dictionaire contient autant d’année que de recensement. Chaque année est associé à la densité de population mesuré. Notons que les densités sont converties en nombre à virgule. Attention, il existe des erreur dans le fichier des densités. Certaines densités sont vides.
{'1001': {'1968': '21,76',
'1975': '23,07',
'1982': '29,91',
'1990': '36,3',
'1999': '45,64',
'2008': '49,59',
'2013': '48,09',
'2018': '48,34'},
'1002': {'1968': '9,62',
'1975': '11,58',
'1982': '14,86',
'1990': '17,38',
'1999': '18,36',
'2008': '21,2',
'2013': '25,79',
'2018': '27,65'},
...
Exercice : Écrivez une fonction read_density_file
qui prend en paramètre le chemin vers le fichier csv insee_rp_hist_1968.csv
et renvoie le dictionnaire comme ci-dessus.
def read_density_file(f):
pass
24.3. Fusion des données#
Nous allons créer un nouveau dictionnaire qui fusionnera les informations contenues dans les deux dictionnaires de coordonnées et de densités. Nous n’intègrerons une ville dans le nouveau dictionnaire que si elle est présente à la fois dans le dictionnaire de coordonées et dans celui de densités.
Voici ce que vous devirez obtenir comme résultat.
{'64001': {'nom': 'Aast',
'latitude': 43.291192630916704,
'longitude': -0.08172502738117142,
'1968': '42,74',
'1975': '24,21',
'1982': '29,47',
'1990': '34,32',
'1999': '40',
'2008': '38,11',
'2013': '37,47',
'2018': '38,95'},
'55001': {'nom': 'Abainville',
'latitude': 48.53272044504441,
'longitude': 5.51487324547426,
'1968': '26,99',
'1975': '23,92',
'1982': '25,53',
'1990': '22,31',
'1999': '23,26',
'2008': '23,48',
'2013': '21,73',
'2018': '21,65'},
...
Exercice : Écrivez une fonction fusion
qui prend en paramètre un dictionnaire de coordonées et un dictionnaire de densité et renvoie un nouveau dictionnaire comme ci-dessus.
def fusion(coordinates, densities):
pass
Si vous affichez la taille des dictionnaires respectifs, vous devriez obtenir les valeurs suivantes. Elles nous indiquent en particulier que le fichier de densité contenait plus de villes que celui des coordonnées.
data = fusion(cities, densities)
print(len(coordinates))
print(len(densities))
print(len(data))
32683
34965
32683
24.4. Heatmap#
Pour créer une heatmap, nous avons besoin d’un ensemble de valeurs de la forme suivante : [lat, lng, weight]
. Le poids, weight
doit être une valeur comprise entre 0 (exclu) et 1 (inclu). Pour plus d’informations, vous pouvez consulter la documentation de la fonction heatmap.
La première étape est donc de trouver quelle est la densité maximum dans nos données pour ensuite pouvoir normaliser les valeurs.
Exercice : Écrire une fonction find_maximum
qui parcours les données et renvoie la densité maximum pour toutes villes et toutes années.
def find_maximum(data):
pass
Vous devriez trouver 27309.96
.
Pour afficher la densité d’une année en particulier, il faut créer une liste de valeurs de la forme suivante.
[(43.291192630916704, -0.08172502738117142, 0.0001280237198559534),
(48.53272044504441, 5.51487324547426, 0.00010983646932824074),
(49.965002813144096, 2.488730102972196, 0.00016185140750861465),
(48.89237421486775, 6.26546345064283, 0.00012064757099993821),
(49.19723198916412, 5.548973627354689, 8.61421943695134e-05),
...
La liste contient de tuple. Chaque tuple est composé de la latitude, la longitude et la densité, normalisé (donc entre 0, exclu et 1, inclu). La fonction suivante semble donnée des résultats intéressants. L’idée est d’avoir une fonction qui n’est pas linéaire pour marqué un peu plus les valeurs extrèmes.
def normalize(i, max_density):
return (i**(1/3)/max_density**(1/3))
Exercice : Écrivez une fonction extract
qui prend en paramètre des données et une année et renvoie une liste de tuples dont la valeur de densité est normalisée.
def extract(data, year, max_density):
pass
On pourra ainsi facilement récupérer les données pour année voulue. data1968 = extract(data, "1968")
.
Nous pouvons maintenant utiliser folium
pour l’affichage d’une heatmap. Voici un exemple de code qui devrait vous permettre de générer la carte ci-dessous. En zoomant, vous verrez que l’on observe quelques abérations, en particulier dans Paris. C’est normal car l’échentillonage n’est pas idéal. Nous avons une unique donnée pour chaque ville, ca ne permet pas une bonne répartition spaciale des informations. Il serais préférable disposer des ces informations au niveau des IRIS.
import folium
import folium.plugins
years = ["1968", "1975", "1982", "1990", "1999", "2008", "2013", "2018"]
max_density = find_maximum(data)
data1968 = extract(data, "1968", max_density)
m = folium.Map([46.4, 2.6], tiles="stamentoner", zoom_start=6)
gradient={0.2: 'blue', 0.4: 'lime', 0.5: 'yellow', 0.95: 'orange', 1: 'red'}
hm1968 = folium.plugins.HeatMap(data1968,
gradient=gradient,
min_opacity=0.01,
max_opacity=0.95,
radius=15,
use_local_extrema=False)
hm1968.add_to(m)
m
Maintenant, nous pouvons même afficher deux années différentes et comparer les résultats.
m = folium.plugins.DualMap(location=(47.6, 3.7), zoom_start=6)
data2018 = extract(data, "2018", max_density)
hm1968 = folium.plugins.HeatMap(data1968,gradient=gradient,
min_opacity=0.01,
max_opacity=0.95,
radius=15,
use_local_extrema=False)
hm2018 = folium.plugins.HeatMap(data2018, gradient=gradient,
min_opacity=0.01,
max_opacity=0.95,
radius=15,
use_local_extrema=False)
hm1968.add_to(m.m1)
hm2018.add_to(m.m2)
m