python
¶Dans ce dernier TP, nous allons aborder l'aspect cartographie sous python
avec le package folium
(à installer donc). En effet, dans les données horodateurs
, nous disposons de deux niveaux d'informations géographiques :
Avec ces deux informations, nous allons donc pouvoir créer des cartes, soit avec des points pour chaque station, soit des formes pour les arrondissements. L'idée sera d'ajouter des couleurs à ces formes, en fonction d'une information tierce (le nombre de transactions, le montant moyen, le type de station, ...).
Le package folium
est une interface entre python
et la librairie leaflet
. Elle s'utilise très facilement, comme nous pouvons le voir ci-dessous pour la création d'une carte zoomée sur la capitale. Les coordonnées indiquées sont la latitude et la longitude de Paris.
import folium
paris = folium.Map(location = [48.856578, 2.351828], zoom_start = 12)
Pour obtenir la carte, il suffit d'appeler l'objet ainsi créé.
paris
La fonction Marker()
permet d'ajouter une marque sur la carte pour signifier un emplacement précis. Il est possible de spécifier un contenu à afficher (sous la forme d'un pop-up) lorsque l'utilisateur va cliquer sur le marqueur. Celui-ci sera placé à la localisation fournie en premier, au format [latitude, longitude]
. Ce contenu est spécifié dans l'argument popup
(ici, une simple chaîne de caractères, mais cela peut être plus élaboré). Il est aussi possible customiser l'icône du marqueur. Une fois ce marqueur créé, il faut l'ajouter à la carte, via la fonction add_to()
.
folium.Marker([48.856578, 2.351828], popup = "PARIS").add_to(paris)
paris
La fonction CircleMarker()
permet elle de créer des cercles, en donnant la localisation du centre et le rayon (via le paramètre radius
). Idem que pour Marker()
, on peut spécifier le contenu de la popup affichée lors d'un clic, et il est nécessaire de l'ajouter à la carte. Il est possible aussi de spécifier la couleur du cercle (via color
) et la couleur de remplissage (via fillColor
).
folium.CircleMarker([48.856578, 2.351828], popup = "PARIS", radius = 10).add_to(paris)
paris
Pour pouvoir ajouter ces informations, nous allons importer les contours des 20 arrondissements parisiens disponibles en téléchargement sur cette page. Les données à récupérer sont celles au format GeoJSON
. Vous devez les sauvegarder, idéalement dans le même répertoire que votre notebook. Dans mon cas, le fichier est dans le répertoire donnees
.
import json
geo = json.load(open("donnees/arrondissements.geojson"))
Le format GeoJSON est de plus en plus utilisé pour représenter des données de type géographique. Il suit des spécifications précises, et peut être utilisé directement comme nous le verrons plus loin.
Dans cet objet, transformé en dictionnaire sous python
, il y a deux éléments : le type et les informations (nommées features
)
geo.keys()
geo["type"]
Nous vérifions bien que nous avons les 20 arrondissements de Paris dans l'objet features
, qui est une list
.
len(geo["features"])
Dans chaque objet de cette liste, nous disposons aussi de différents objets de type Feature
.
geo["features"][0].keys()
geo["features"][0]['type']
Dans le champs properties
, il y a différentes informations utiles, dont les coordonnées longitude et latitude du centre.
geo["features"][0]['properties']
Et dans la partie geometry
, nous voyons que c'est un Polygon
qui est représenté, avec toutes les coordonnées des sommets de ce polygone.
geo["features"][0]['geometry']
Avec les informations contenues dans geom_x_y
, nous allons pouvoir ajouter un marqueur pour chaque arrondissement, en mettant dans la popup, le nom de l'arrondissement.
paris_arr_marker = folium.Map(location = [48.856578, 2.351828], zoom_start = 12)
for arr in geo["features"]:
prop = arr["properties"]
folium.Marker(prop["geom_x_y"], popup = prop["l_ar"]).add_to(paris_arr_marker)
paris_arr_marker
Toujours avec les mêmes informations, nous pouvons disposer des cercles pour chaque arrondissement. Ici, nous décidons de régler la taille des cercles (via radius
) en fonction de la surface des arrondissements. Nous remarquons que nous devons faire cela manuellement (ici, on divise la surface par 1000000 pour avoir des tailles raisonnables).
paris_arr_circle = folium.Map(location = [48.856578, 2.351828], zoom_start = 12)
for arr in geo["features"]:
prop = arr["properties"]
folium.CircleMarker(prop["geom_x_y"],
popup = prop["l_ar"],
radius = prop["surface"] / 1000000).add_to(paris_arr_circle)
paris_arr_circle
Enfin, il est possible de faire des cartes choroplètes, dans lesquelles les zones sont coloriées selon une mesure statistique.
Pour cela, nous devons devons utiliser la fonction choropleth()
de la carte créée. Nous passons dans le paramètre geo_str
les données contenues dans le fichier GeoJSON
importées plus haut.
paris = folium.Map(location = [48.856578, 2.351828], zoom_start = 12)
paris.choropleth(geo_str = geo)
paris
Bien évidemment, nous désirons ajouter une couleur. Pour cela, nous avons besoin d'un DataFrame
contenant deux variables :
GeoJSON
Pour le construire, nous allons récupérer le numéro d'arrondissement (item c_ar
dans properties
) et la surface (surface
dans properties
). Voici comment les récupérer.
[arr["properties"]["c_ar"] for arr in geo["features"]]
[arr["properties"]["surface"] for arr in geo["features"]]
Nous créons donc maintenant le DataFrame
avec ces deux informations.
import pandas
df = pandas.DataFrame({
"Arrondissement" : [arr["properties"]["c_ar"] for arr in geo["features"]],
"Surface" : [arr["properties"]["surface"] for arr in geo["features"]]
})
df
Pour relier ces informations à la carte, toujours dans la fonction choropleth()
, nous devons définir les éléments suivants :
geo_str
: les contours au format GeoJSON
key_on
: l'item dans le GeoJSON
avec lequel nous ferons la jointuredata
: le DataFrame
dans lequel nous avons les informations statistiquescolumns
: les deux colonnes à prendrefill_color
: la palette de couleurs à utiliser (provenant de Color Brewer)Nous obtenons maintenant la carte suivante.
paris = folium.Map(location = [48.856578, 2.351828], zoom_start = 12)
paris.choropleth(geo_str = geo, key_on = "feature.properties.c_ar",
data = df, columns = ["Arrondissement", "Surface"],
fill_color = "Spectral")
paris