Réutilisation automatique des données de Météo France

Pour un de mes projets en cours, j’avais besoin de données météorologiques qui puissent être mises régulièrement à jour. Je présente ici quelques astuces pour tirer pleinement parti de notre ami R et de ses multiples packages :

  • récupérer des données publiques automatiquement, sans avoir à télécharger manuellement les fichiers .csv
  • les mettre en forme avec dplyr et tidyr
  • les représenter dans une carte interactive avec leaflet
  • mettre un tableau différent dans une fenêtre popup pour chaque point de la carte avec leafpop (on peut mettre aussi des graphiques, mais comme c’est en cours de développement, la fonctionnalité à encore quelques bugs, je préfère ne pas la mettre ici pour l’instant)
  • notez que j’utilise ici le nouveau pipe |> (pour %>%) et le raccourci \(x) (pour function(x)) de R 4.0

Remarque : il faut une bonne connexion internet pour que le téléchargement ne prenne pas trop de temps (ou modifier options(timeout = 60) - le comportement par défaut signifie qu’au-delà de 60 secondes, le téléchargement est interrompu automatiquement par R).

Voici le code par étape :

Import des données

D’abord on charge les packages dont on aura besoin.

# chargement des packages
library(dplyr)
library(tidyr)
library(echarts4r)
library(leaflet)
library(leafpop)

Ensuite, on récupère les données gratuites de Météo-France. Je suis passée par ce lien : donneespubliques.meteofrance.fr. Il est important de respecter la licence de ces données (paragraphe : Condition d’accès), c’est à dire de les sourcer correctement si on les réutilise.

Les données qui m’intéressent sont les suivantes :

  • les données concernant les stations météorologiques (contenant leurs coordonnées en particulier)
  • les données mensuelles de suivi météo

Les premières sont faciles à récupérer, il suffit de copier le lien csv (clic droit > copier le lien) de la liste des stations essentielles.

Les secondes sont un peu plus retorses, car le lien de téléchargement n’est pas accessible en faisant un clic droit sur le bouton “télécharger”. De plus, elles sont compressées avec gzip et ne sont pas directement sous format csv.

Pour trouver le lien de téléchargement, il faut cliquer sur le bouton “télécharger”, puis annuler l’ouverture du fichier.

Le lien qui termine en .csv.gz à copier (clic droit) se trouve ici :

Nous remarquerons que les fichiers sont nommés avec le format climat.aaaamm (par exemple, 202103 pour mars 2021), et nous pouvons en profiter pour en déduire le nom des autres fichiers, sans avoir à faire la même manipulation pour chacun des mois qui nous intéresse.

C’est maintenant que l’on peut faire un test d’import des données dans R pour un seul mois :

# Test
# données stations :
read.csv2("https://donneespubliques.meteofrance.fr/donnees_libres/Txt/Synop/postesSynop.csv") |> head() # ici est le premier lien copié
ID Nom Latitude Longitude Altitude
7005 ABBEVILLE 50.136000 1.834000 69
7015 LILLE-LESQUIN 50.570000 3.097500 47
7020 PTE DE LA HAGUE 49.725167 -1.939833 6
7027 CAEN-CARPIQUET 49.180000 -0.456167 67
7037 ROUEN-BOOS 49.383000 1.181667 151
7072 REIMS-PRUNAY 49.209667 4.155333 95

# données suivi météo pour mai 2020
url("https://donneespubliques.meteofrance.fr/donnees_libres/Txt/Climat/climat.202005.csv.gz") |> # ici, le second
  gzcon() |> # lis un fichier .gz
  readLines() |> # lis ligne par ligne le résulat
  textConnection() |> # extrait le .csv du .gz (ne me demandez pas comment ça marche !)
  read.csv2(dec = ".") |> # l'import classique, enfin ! Il faut préciser que les séparateurs décimaux sont des points pour que les colonnes numériques soient bien reconnues en tant que telles
  select(1:6) |>
  head() # pour l'exemple, je ne montre que les 6 premières lignes et les 6 premières colonnes
NUM_POSTE DAT PSTATM PMERM TMMOY TMSIGMA
7005 2020-05-01 00:00:00 1012.9 1021.5 13.6 3.5
7015 2020-05-01 00:00:00 1015.6 1021.2 14.7 3.7
7020 2020-05-01 00:00:00 1020.3 1021.4 12.6 1.7
7027 2020-05-01 00:00:00 1013.3 1021.4 13.3 2.9
7037 2020-05-01 00:00:00 1002.9 1021.1 14.2 3.6
7072 2020-05-01 00:00:00 1009.0 1020.4 13.9 3.2

Ok, ça fonctionne ! Maintenant, je voudrais automatiser l’import des données de suivi pour les printemps des années 2018 à 2020 en métropole (hé, pourquoi pas ?). Je vais créer des fonctions simples qui vont m’aider.

# fonction pour lister les dates qui m'intéressent au format aaaamm
# annees : vecteur d'années
lister_dates <- \(annees) paste0(
    rep(annees, each = 3),
    rep(c("03", "04", "05"), times = length(annees)) # les données de mars, avril et mai seulement ; attention les "0" comptent !
  )

# exemple
lister_dates(2018:2020)
## [1] "201803" "201804" "201805" "201903" "201904" "201905" "202003" "202004"
## [9] "202005"
# fonction pour importer un seul mois, comme dans le test précédent
# lien : url récupérée qui se termine par .csv.gz
importe_un_mois <- \(lien){ 
      lien|>
        url()|>
        gzcon() |>
        readLines() |>
        textConnection() |>
        read.csv2(dec = ".") |>
        select(NUM_POSTE, DAT, TMMOY, RR)
}

# exemple
importe_un_mois("https://donneespubliques.meteofrance.fr/donnees_libres/Txt/Climat/climat.202004.csv.gz") |> 
  head()
NUM_POSTE DAT TMMOY RR
7005 2020-04-01 00:00:00 12.4 29
7015 2020-04-01 00:00:00 12.8 41
7020 2020-04-01 00:00:00 11.0 25
7027 2020-04-01 00:00:00 11.9 53
7037 2020-04-01 00:00:00 13.2 25
7072 2020-04-01 00:00:00 12.3 30

Et voici maintenant l’import en tant que tel :

# Import
meteo <- lister_dates(2018:2020) %>% # choisis les années à importer (possibilité de 1990 à 2020)
  sprintf("https://donneespubliques.meteofrance.fr/donnees_libres/Txt/Climat/climat.%s.csv.gz", .) |> # création des url de téléchargement
  lapply(importe_un_mois) |> # importe chaque mois de données avec la fonction maison
  bind_rows() |> # les assemble en un seul tableau
  inner_join( # importe les infos des stations météo (ville et coordonnées géographiques)
    read.csv2("https://donneespubliques.meteofrance.fr/donnees_libres/Txt/Synop/postesSynop.csv", dec = "."),
    by = c("NUM_POSTE" = "ID") # nom de la colonne permettant de faire le lien entre les 2 tables
  ) |>
  as_tibble() |> # transforme en tibble pour un plus joli format de sortie
  dplyr::filter(Latitude > 25) |> # conserve uniquement les stations métropole (élimine outre-mer)
  mutate(
    DAT = as.Date(DAT), # passe la date en format Date
    Mois = format(DAT, format = "%m/%Y") # récupère les mois/années
  )

head(meteo)
NUM_POSTE DAT TMMOY RR Nom Latitude Longitude Altitude Mois
7005 2018-03-01 5.8 70 ABBEVILLE 50.13600 1.834000 69 03/2018
7015 2018-03-01 5.6 67 LILLE-LESQUIN 50.57000 3.097500 47 03/2018
7020 2018-03-01 7.5 108 PTE DE LA HAGUE 49.72517 -1.939833 6 03/2018
7027 2018-03-01 6.5 61 CAEN-CARPIQUET 49.18000 -0.456167 67 03/2018
7037 2018-03-01 5.6 110 ROUEN-BOOS 49.38300 1.181667 151 03/2018
7072 2018-03-01 5.6 50 REIMS-PRUNAY 49.20967 4.155333 95 03/2018

Carte température

# Passage des données de température en format court pour les afficher dans la carte
table_temp <- meteo |>
  pivot_wider(id_cols = Longitude:Nom, names_from = "Mois", values_from = "TMMOY")

head(table_temp)
Longitude Latitude Nom 03/2018 04/2018 05/2018 03/2019 04/2019 05/2019 03/2020 04/2020 05/2020
1.834000 50.13600 ABBEVILLE 5.8 12.0 14.3 8.8 10.3 12.3 7.3 12.4 13.6
3.097500 50.57000 LILLE-LESQUIN 5.6 12.7 15.9 9.0 10.9 12.6 7.3 12.8 14.7
-1.939833 49.72517 PTE DE LA HAGUE 7.5 10.8 12.4 9.8 10.1 12.2 8.8 11.0 12.6
-0.456167 49.18000 CAEN-CARPIQUET 6.5 11.4 13.3 8.9 9.6 11.9 7.8 11.9 13.3
1.181667 49.38300 ROUEN-BOOS 5.6 12.0 14.4 8.5 10.1 11.9 7.1 13.2 14.2
4.155333 49.20967 REIMS-PRUNAY 5.6 12.4 15.5 8.2 9.8 11.9 7.3 12.3 13.9
# Créé et affiche la carte des données de température
leaflet(data = table_temp, options = leafletOptions(maxZoom = 9), width = "100%") |> # initialise la carte
  addProviderTiles("Stamen.Watercolor") |> # ajoute un fond de carte (source : http://maps.stamen.com/#watercolor)
  addMarkers( # ajoute les points représentant les stations
    ~Longitude,
    ~Latitude,
    popup = popupTable(table_temp, row.numbers = FALSE, feature.id = FALSE, zcol = 3:12), # la table de température apparaît quand on clique sur la station
    icon = list(iconUrl = "cloud-sun-rain-solid.svg", iconSize = c(30,30)) # icone personnalisée
  )

Carte pluviométrie

# Passage des données de pluviométrie en format court pour les afficher dans la carte
table_pluvio <- meteo |>
  pivot_wider(id_cols = Longitude:Nom, names_from = "Mois", values_from = "RR")

head(table_pluvio)
Longitude Latitude Nom 03/2018 04/2018 05/2018 03/2019 04/2019 05/2019 03/2020 04/2020 05/2020
1.834000 50.13600 ABBEVILLE 70 71 60 56 40 24 75 29 27
3.097500 50.57000 LILLE-LESQUIN 67 48 85 81 35 32 66 41 4
-1.939833 49.72517 PTE DE LA HAGUE 108 40 21 49 31 30 69 25 29
-0.456167 49.18000 CAEN-CARPIQUET 61 109 46 39 40 48 44 53 42
1.181667 49.38300 ROUEN-BOOS 110 73 61 64 43 48 66 25 34
4.155333 49.20967 REIMS-PRUNAY 50 31 36 34 20 64 53 30 23
# Créé et affiche la carte des données de pluviométrie
leaflet(data = table_pluvio, options = leafletOptions(maxZoom = 9), width = "100%") |>
  addProviderTiles("Stamen.Watercolor") |>
  addMarkers(
    ~Longitude,
    ~Latitude,
    popup = popupTable(table_pluvio, row.numbers = FALSE, feature.id = FALSE, zcol = 3:12),
    icon = list(iconUrl = "cloud-sun-rain-solid.svg", iconSize = c(30,30))
  )

Et voilà le travail ! N’oubliez pas de cliquer sur les stations pour voir apparaître les données ☺

Anna Doizy
Anna Doizy
Freelance

Conseil et formation en statistiques.