Hello,

En ces temps de confinement j’ai recherché une carte de France avec les cas confirmés par région, en vain.
Que cela ne tienne, on va la realiser !

Photo carte-covid19

Pour ce faire, il faut dans un premier temps trouver une source fiable qui sera mise à jour. Et apres un peu de recherche, cet article sera parfait pour l’excercice.

Alors on part d’un article, et on souhaite en faire une carte de france.
Par quelles etapes doit-on passer pour avoir notre resultat ?

  1. Récupérer les données dans le tableau de l’article.
  2. Organiser ces données.
  3. Projeter ces données sur une carte.

Etape 1:

Pour récupérer ce que nous avons besoin, nous utiliserons la librairie Beautiful Soup.
Elle nous permettra de scraper le tableau contenant les données et d’en faire ce qu’on voudra par la suite.
Mais avant tout ca on a besoin, de voir dans le code de la page entre quelles balises nos données se trouvent pour aider notre librairie à faire le job.

Lorsque vous retournez voir l’article, dans votre navigateur, faites F12 pour ouvrir l’inspecteur de code. On voit que nos données sont dans un tableau.

<table style="width:731px;" border="1">
  <thead></thead>
  <tbody>
    <tr>
      <td style="width:380px;">Auvergne-Rhône-Alpes</td>
      <td style="width:350px;">1 266</td>
    </tr>
  </tbody>
</table> 

Par chance il n’y qu’un seul tableau sur cette page, alors allons-y en bourrins.
On va récupérer toutes les balises <td> !

import requests
from bs4 import BeautifulSoup

url = 'https://www.santepubliquefrance.fr/maladies-et...et-monde'
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
result = soup.find_all('td')

Nous voila avec nos données, maintenant on va les organiser correctement.

Etape 2:

Le result obtenu est une liste en bordel, et il y a des lignes que nous ne voulons pas.
Ici j’ai fais le choix de créer un dictionnaire, en itérant deux par deux dans la liste result.

DATA = {}
for i in range(0, len(result)):
        if i % 2 == 0:
           region = result[i].text
           number = result[i+1].text
           # ici number = '3 405' par exemple
           # Et plus tard nous aurons besoin de ce nombre en integer et non string
           # Alors on dégage les espaces pour le convertir plus facilement plus bas.
           number = number.replace(' ', '')
       if region == 'Total Métropole' or region == 'Total Outre Mer':
               pass
       else:
               DATA.append(
                       {'Region': region,
                        'Persons': int(number)}
               )

Nous voici avec une constante DATA qui est un dictionnaire sympathique avec nos données !

Maintenant on passe aux choses serieuses.

On va utiliser la librairie folium, et sa classe Choropleth. Ce qui va nous permettre d’appliquer nos données par région proprement sur une carte de France qui sera elle même coupée par région.

De quoi a besoin la classe Choropleth du coup:

folium.Choropleth(
    columns=['Region', 'Persons'],
    data=dataset,
    fill_color='BuPu',
    fill_opacity=0.7,
    key_on='feature.properties.nom',
    legend_name='Cas confirmes',
    line_opacity=0.2,
    geo_data='regions.geojson',
    name='test',
    )

columns: Les colonnes en liens avec notre carte.
data: objet représentant nos données.
key_on: Le chemin de votre geojson (on va detailler plus bas).
geo_data: Le path vers votre fichier geojson.
Les autres arguments ne sont pas trop compliqués à comprendre.

Donc ici, il va nous falloir deux fichiers:

  • Un GeoJSON représentant les coordonnées de nos regions.
  • Un CSV avec les données qu’on veut afficher sur notre carte.

Pour le geojson, une personne formidable a deja fait le boulot pour nous et je le remercie fortement.
Vous pouvez récupérer le fichier sur son site: gregoiredavid.fr
Et bien évidemment choisir ‘Regions’, puis ‘Telecharger’.

Maintenant faisons notre csv/

import csv

csv_columns = ['Region','Persons']
csv_file = "regions.csv"
try:
	with open(csv_file, 'w') as csvfile:
		writer = csv.DictWriter(csvfile, fieldnames=csv_columns)
		writer.writeheader()
		for d in DATA:
			writer.writerow(d)
except IOError:
	print("I/O error")

Et bim, on a tout ce qu’il nous faut pour commencer le taff sur notre carte.

Etape 3:

import folium
import pandas

# Création de notre carte avec les coordonnées de la France.
m = folium.Map(
            location=[46.8534, 2.3488],
            zoom_start=6
	    )
# Un bel objet data qui est demandé par Choropleth.
dataset = pandas.read_csv('regions.csv')

folium.Choropleth(
		columns=['Region', 'Persons'],
		data=dataset,
		fill_color='BuPu',
		fill_opacity=0.7,
		key_on='feature.properties.nom',
		legend_name='Cas confirmés',
		line_opacity=0.2,
    geo_data='regions.geojson',
    highlight=True,
    name='covid19',
).add_to(m)

folium.LayerControl().add_to(m)

# Sauvegarde le tout dans un beau fichier index.html.
m.save('index.html')

Dans la génération de l’objet Choropleth, il y a une choses à comprendre; c’est le lien entre columns et key_on.

  • columns correspond à votre fichier csv.
    Et la premiere colonne, ici Region, doit correspondre avec la valeur donnée dans key_on.
Region,Persons
Île-de-France,3818
Auvergne-Rhône-Alpes,1101
Bourgogne-Franche-Comté,770
Bretagne,346
  • key_on correspond à votre fichier geojson.
    Et sa valeur, est le chemin vers la donnée commune à votre csv. Ici, le nom des régions.
{
"type": "FeatureCollection",
"features": [
	     {"type": "Feature",
	      "geometry": (...),
	      "properties": {"code": "11",
			     "nom": "Île-de-France"}}
	    ]

}

Yes, c’est bon, vous avez tout pour refaire un mapping des régions avec folium !

Je vous invite à regarder le code source sur mon github pour voir de légères améliorations sur ce projet.
Ou visiter directement covid19-map.fr.

Puis surtout, restez chez vous. C’est le moment de faire plein de petit projet pour apprendre de nouvelles choses ! Profitez-en :)

Bon courage à toutes et à tous en ces moments particuliers.