Dans ce court tutoriel, je vais vous montrer comment “découper” votre jeu de données selon les modalités d’une variable catégorielle (une espèce, un pays etc..), pour ensuite exporter ces données en de multiples fichiers csv, ou en multiples feuilles d’un même classeur Excel.
Pour illustrer cet exemple, je vais employer les données world-records.csv
, du projet Tidytuesday (https://github.com/rfordatascience/tidytuesday).
Pour celles et ceux qui ne connaissent pas TidyTuesday, c’est un projet initié par Thomas Mock qui consiste, chaque semaine (le mardi), à mettre à disposition un jeu de données, au format tidy, pour permettre à tous ceux qui le souhaitent de réaliser une data visualisation et une analyse de ce jeu de données, et éventuellement de partager son travail.
Les données world-records.csv
sont relatives aux records du monde sur le jeu vidéo Mario Kart World
, sur Nintendo 64.
Pour les télécharger rapidement, nous pouvons employer la fonction read_csv()
du package readr
(qui appartient au super package tidyverse
) :
install.packages("tidyverse")
library(tidyverse)
records <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2021/2021-05-25/records.csv')
Ces données contiennent une variable track
qui correspond aux 16 circuits du jeu :
records$track <-as.factor(records$track)
levels(records$track)
## [1] "Banshee Boardwalk" "Bowser's Castle" "Choco Mountain"
## [4] "D.K.'s Jungle Parkway" "Frappe Snowland" "Kalimari Desert"
## [7] "Koopa Troopa Beach" "Luigi Raceway" "Mario Raceway"
## [10] "Moo Moo Farm" "Rainbow Road" "Royal Raceway"
## [13] "Sherbet Land" "Toad's Turnpike" "Wario Stadium"
## [16] "Yoshi Valley"
C’est selon cette variable que nous allons découper le jeu de données, pour créer, dans un premier temps, 16 fichiers csv (un par circuit), et les exporter automatiquement dans le dossier data du projet R.
Vous trouverez plus d’informations concernant la création de projets R dans mon article “7 étapes pour organiser son travail sous R” .
Dans un second temps, nous exporterons les données de chaque circuit dans un seul et même classeur Excel, contenant une feuille par circuit.
Nous allons réaliser les exportations multiples dans un dossier nommé data
que nous allons placer à la racine du projet R. Pour créer ce dossier data
, vous pouvez employer l’outil de R Studio :
Ou employer directement la commande suivante :
dir.create("data")
Pour réaliser ces exportations multiples en fichiers csv, nous allons employer plusieurs fonctions du package purrr
qui appartient au super package tidyverse
. Il est donc nécessaire d’installer et d’ouvrir ce package :
#install.package("tidyverse")
library(tidyverse)
Pour réaliser ces exportations multiple en .csv
nous allons :
nest()
du package purrr
(contenu dans tidyverse
).pwalk()
,du package purrr
, et write_csv2()
du package readr
.
Voici les lignes de commandes qui permettent de faire cette exportation en multiples fichiers csv :
records %>%
group_by(track) %>%
nest() %>%
pwalk(~write_csv2(x = .y, file = paste0("data/",.x, ".csv") ))
Si tout s’est bien déroulé, vous devriez voir apparaître vos 16 fichiers csv dans le dossier data :
Remarque : je me suis largement inspiré de cette page pour créer le code: https://community.rstudio.com/t/map-write-csv/33292/2
La fonction nest()
permet de créer un data frame nesté. Il s’agit d’un data frame contenant deux colonnes :
track
qui contient le nom du circuit,data
qui contenant les données de ce circuit, sous la forme d’un data frame.
Vous pourrez le visualiser en utilisant les commandes suivantes:
tracks_nest <- records %>%
group_by(track) %>%
nest()
View(tracks_nest)
Les exportations sont des effets “immatériels” (ou side-effect) car aucun objet n’est retourné par la fonction (il n’y a pas de création d’objet dans R). On parle alors de side effect
. Ces side effects sont générés par la fonction walk()
du package purrr
(alors que la génération d’output se fait avec une fonction map()
).
La lettre p
devant walk
veut dire “parallèle”. D’après ce que j’ai compris (n’hésitez pas à me corriger si besoin) cela correspond au fait que la fonction réalise une itération sur chaque élément de .x
et de .y
parallèlement (le ième élément de x correspondant au ième élément de y…) (voir juste en dessous pour l’explication de ce que sont .x
et .y
). Si seulement .x
était utilisé, alors on emploierait la fonction walk()
tout court.
Là encore, d’après ce que j’ai compris, dans la commande pwalk(~write_csv(x = .y, path = paste0("data/",.x, ".csv") ))
:
.y
correspond à la seconde colonne du data frame nesté, c’est-à-dire la colonne data qui contient les données. Cela permet d’indiquer que ce que l’on souhaite exporter se trouve dans cette seconde colonne..x
correspond à la première colonne de ce data frame nesté. La fonction paste0("data/",.x, ".csv")
permet de créer automatiquement le nom du fichier csv, en utilisant ce qui est dans la colonne .x
, c’est-à-dire le nom du circuit.La procédure est plus simple. Il s’agit de :
split()
write_xlsx()
du package writexl
pour exporter chaque élément de la liste (chaque data frame correspondant à un circuit) dans une feuille Excel d’un même classeurVoici les lignes de commande :
library(writexl)
records %>%
split(.$track) %>%
writexl::write_xlsx(path = "data/mario_kart.xlsx")
La fonction write_xlsx()
prend en entrée la liste des data frame (grâce au pipe %>%
) et créé automatiquement des feuilles avec le nom des éléments de la liste.
Dit autrement, la liste contient 16 éléments, qui sont les 16 data frame. Ces 16 éléments ont des noms, qui ont été générés automatiquement lors du découpage avec la fonction split()
. Ces noms sont ceux des circuits.
Pour mieux comprendre, ce passage en format list
, et le nom des éléments, vous pouvez employer ces commandes :
records_ls <- records %>%
split(.$track)
names(records_ls)
## [1] "Banshee Boardwalk" "Bowser's Castle" "Choco Mountain"
## [4] "D.K.'s Jungle Parkway" "Frappe Snowland" "Kalimari Desert"
## [7] "Koopa Troopa Beach" "Luigi Raceway" "Mario Raceway"
## [10] "Moo Moo Farm" "Rainbow Road" "Royal Raceway"
## [13] "Sherbet Land" "Toad's Turnpike" "Wario Stadium"
## [16] "Yoshi Valley"
Au final, vous deviez obtenir le classeur suivant :
Remarque : cette solution a été proposée par Martin Chan.
Vous trouverez une très bonne introduction (en français) au package purrr
sur le site de Lise Vaudor.
Vous trouverez encore des liens vers des tutoriels dans mon article “Liste de ressources pour le package purrr”.
Le sujet de cet article m’a été soufflé par une lectrice du blog (et aussi stagiaire d’une de mes formations), qui avait ce besoin d’exporter vers de multiples fichiers.
J’espère que ce court tutoriel rendra également service à un grand nombre d’entre vous . Je pense que c’est une bonne chose d’avoir ces deux petits bouts de code dans sa boite à outils !
Si cet article vous a plu, ou vous a été utile, et si vous le souhaitez, vous pouvez soutenir ce blog en faisant un don sur sa page Tipeee
Enregistrez vous pour recevoir gratuitement mes fiches “aide mémoire” (ou cheat sheets) qui vous permettront de réaliser facilement les principales analyses biostatistiques avec le logiciel R et pour être informés des mises à jour du site.
2 Responses
Bonjour Claire,
ce procédé très utile que vous rappelez m’a fait repenser aussi à la fonction group_walk, qui permet d’éviter un nest() et donc de simplifier un peu l’écriture :
records %>%
group_by(track) %>%
group_walk(~write_csv2(.x , file = paste0(“data/”, .y$track, “.csv”) ))
Bonjour Eric,
merci pour le partage, je ne connaissais pas du tout cette possibilité !
A bientôt !