1 Avant de commencer…

-> Vérification des installations et résolution des problèmes éventuels

-> Exprimez vos difficultés et incompréhensions pour éviter qu’elles s’accumulent

-> Jouez le jeu des exercices : c’est un moyen pour se familiariser avec l’écriture de R

-> Accès au support de formation :

Le support vous aide à suivre la formation, vous pouvez directement copier/coller les codes proposés. Il peut être téléchargé sur https://github.com/Grisoudre/quantilille21_intror (télécharger l’ensemble des fichiers : Code > Download zip). Le fichier .html contient l’ensemble de la présentation et s’ouvre via un nagivateur web (firefox, chrome, opera, etc).

1.1 Mise en place de la session de travail

-> Dès maintenant, créez un dossier consacré à la formation, par exemple appelé “Quantilille 21 - intro R” :

1.1.1 Programme de la demi-journée (3h)

  1. Présentation de R/Rstudio, de l’environnement de travail et du {tidyverse}
  2. Importation des données
  3. Exploration des données
  4. Mise en forme et modification des données
  5. Opérations sur les tables

1.2 Données utilisées

Nous allons travailler sur des données portant sur les accidents de la route 2019 décrits par les forces de l’ordre (police, gendarmerie) : https://www.data.gouv.fr/fr/datasets/base-de-donnees-accidents-corporels-de-la-circulation/

En général, voici le type de fichiers qu’on reçoit lorsqu’on contacte les producteurs d’une enquête :

  • Fichier de données brutes -> ici, les 4 fichiers .csv
  • Dictionnaire des codes -> le fichier .pdf
  • Questionnaire -> pas de questionnaire dans ce cas
  • Documentation méthodologique -> le fichier .pdf

Identifiants :

Permettant de joindre les tables

  • Num_Acc : Identifiant unique de l’accident
  • Num_veh : Identifiant (non unique) véhicule, un accident peut concerner plusieurs véhicules
  • id_vehicule : Ajout de 2019, identifiant unique du véhicule

1.3 Comment appréhender des tables de données ?

  • “Logiciels clic-boutons” : Excel, Excel Stat… et à un autre niveau SPAD, SPSS, Sphinx, ModaLisa.

Interface avec menus et options évitant de passer par des lignes de commande. Facilité d’accès mais tâches répétitives et non enregistrées. Pas d’historique des actions effectuées. Problème de la reproductibilité et de la transférabilité des documents produits.

  • Langages de programmation : essentiellement Python, SAS, R, SPSS…

Chaque action est produite par une ligne de commande exécutée dans un IDE (environnement de développement intégré). Historique et reproductibilité garantis, plus de possibilités.

2 Présentation de R/Rstudio, de l’environnement de travail et du {tidyverse}

2.1 R

= Langage “Brut”

R est un dérivé gratuit (licence GNU GPL) du langage de statistique S. C’est un projet collaboratif et donc ouvert à tous. Il est entretenu par le R Development Core Team (CRAN). C’est un langage permettant de produire des statistiques descriptives comme des statistiques avancées. Ses fonctionnalités sont étendues ; il offre un large choix d’options graphiques. Il permet de développer ses propres fonctions et d’utiliser des fonctions développées par d’autres chercheurs, ingénieurs ou développeurs.

  • Gratuit et opensource

  • Multi-plateformes (Windows, Linux, OS X)

  • Produit simplement des statistiques avancées :

    • Statistiques descriptives, inférentielles
    • Représentations graphiques
    • Analyses factorielles
    • Modélisations
    • Analyses de réseaux
    • Cartographies, etc.
  • Grâce aux “packages” (extensions, bibliothèques de fonctions), les fonctionnalités sont très étendues et en font un langage complet

  • Importante communauté :

    • Tutoriels et aides sur le web
    • Développement constant de nouvelles fonctionnalités, interfaces et mises à jour régulières
  • Reproductibilité et historique :

    • Partager simplement des rapports commentés (pdf, word, htlm, présentations) et applications en ligne ;
    • Reproduire et adapter des procédures et méthodes réalisées pour d’autres projets (ex : Rapports annuels);
  • Permet de ne pas subir des options par défaut sans les comprendre

  • Compatible avec d’autres langages, exportations graphiques avancées

… Quelques inconvénients :

  • Les fonctionnalités (et bibliothèques) sont très souvent mises à jour et nécessitent d’être maintenues.
  • Les fonctionnalités sont créées par les contributeurs et les syntaxes peuvent varier

2.2 RStudio

= Interface de développement

La console diponible avec R est très rudimentaire (On utilise R dans le terminal sur linux), peu conviviable et devient complexe lorsque vous avez plusieurs fichiers et projets à gérer.

Il est conseillé d’utiliser un logiciel offrant un espace de travail plus agréable et complet. RStudio est un environnement de développement pour l’écriture et la visualisation de scripts R. :

  • Il est également gratuit
  • Il offre un éditeur de texte (coloration donnant des repères, auto complétion, indentation)
  • Permet un affichage simultané des scripts, sorties, fichiers, graphiques, aides
  • Intègre une série de modules supplémentaires (Addins)
  • Les fonctionnalités de projets facilitent l’accès aux dossiers (association entre la session de travail et les dossiers-cibles) et de façon plus avancée, la création d’applications et de rapports

2.3 Téléchargements R/RStudio

- (1) Téléchargement du langage R :

https://cran.r-project.org/

puis “Downolad for…” en fonction du système d’exploitation ; faire bien attention à télécharger la version compatible avec la version de votre système d’exploitation (surtout sur mac, vérifier la compatibilité indiquée dans la colonne “latest release”)

- (2) Télécharger et installer l’IDE RStudio :

RStudio : https://www.rstudio.com/products/rstudio/download/#download : idem, faire attention à prendre la version correspondant au système d’exploitation

2.4 Les packages

= Bibliothèques de fonctions, env. extensions

  • Packages : Extensions ajoutées à votre session de travail, une fois installées et chargées. Les packages sont des bibliothèques de fonctions supplémentaires développées par d’autres personnes.

  • Les packages “officiels” sont validés par la communauté de R (CRAN). Ils sont tous accompagnés d’une documentation (document pdf issu du site cran.r-project.org).

    • 1. L’installer (une seule fois, vous l’avez déjà fait avant la formation) :
2.4.0.0.1 Pour installer un package validé par le CRAN :
install.packages("tidyverse", dep=T)
2.4.0.0.2 Pour utiliser un package développé qui n’est pas sur un serveur-miroir du CRAN :
remotes::install_github("NomUtilisateur/NomPackage")

concrètement, on fait appelle au packages {remotes} en écrivant le nom du package puis :: pour désigner qu’on utilise une fonction de ce package -> intérêt : évite de charger toutes les fonctions quand on en utilisera qu’une une seule fois.

Cette étape d’installation des packages est délicate : R évoluant rapidement, la compatibilité entre les packages et entre les packages et la version utilisée de R n’est pas toujours garantie.

  • 2. Le charger (à refaire pour chaque session) :
    • En ligne de commande :
library(tidyverse)
library(questionr)

/!\ Il est préférable d’écrire ces lignes afin que les packages soient automatiquement définis et que les fonctions associées fonctionnent.

On recommande aussi de mettre ces lignes en début de script.

library() est équivalent à require() que vous rencontrerez peut-être.

2.5 {tidyverse}

Une des limites du langage R est aussi une de ses qualités : la possibilité de créer et de diffuser des fonctions et des packages facilement implique que, selon les packages utilisés, la syntaxe peut varier.

Le package {tidyverse} regroupe d’autres packages complémentaires qui ont été pensés selon une syntaxe commune et qui commence à être largement partagée. C’est pourquoi, pour cette demi-journée, je vous présenterai essentiellement des fonctionnalités {tidyverse} au détriment du code en R {base}. Nous nous y intéressons particulièrement pour ses fonctionnalités de mise en forme des données. Les principaux “sous-packages” de {tidyverse} sont :

  • readr : importation
  • tibble : format des tableaux de données
  • forcats : mise en forme des facteurs
  • stringr : modification de chaînes de caractères
  • tidyr et dplyr : mise en forme de tableaux
  • ggplot2 : graphiques

2.6 Environnement de RStudio

On ouvre RStudio pour découvrir l’interface, puis on créera un projet associé aux dossiers et sous-dossiers qu’on vient de faire.

  • Console : Retour direct des instructions (sans sauvegarde). La console permet de vérifier que les lignes de commande ont bien été exécutées et de comprendre les erreurs éventuelles afin de les corriger. “>” = prêt à recevoir des instructions.

Instruction simple :

1+1

Et touche Entrée

  • Script : Zone d’écriture des instructions qui constitue le programme ou script qui sera gardé en mémoire (après sauvegarde) Pour ouvrir un script : ctrl+shift+N / Fichier > new file > R script
1+1

Sélectionner la ligne puis Ctrl + entrée ou bouton “Run”. Ou “Source” pour tout exécuter

2.7 Créer un objet dans R

Dans R, on manipule des objets qu’on crée directement dans l’interface/session. En fait, ce sont des objets virtuels qui n’existent que dans la session de travail, temps qu’on ne les exporte pas.

Pour créer un objet, on lui donne un nom, puis on écrit <- afin de signaler qu’on va définir un contenu à cet objet, enfin on définit son contenu :

# Création d'une valeur
Objet <- 5
Objet <- Objet + 2
Objet + Objet
class(Objet)
# Création d'une chaîne de caractères
Texte <- "Mon texte"
# texte
class(Texte)
# Supprimer des objets :
rm(Texte, Objet)

Attention :

  • Respect de la casse
  • Ni accent, ni espace, ni caractère spécial en-dehors de "_"

Les objets peuvent être de différentes natures : chaîne de caractère, chiffre, suite d’éléments (vecteur), tableau, matrice, image, graphique, etc. Ils sont toujours accessibles par déclaration et créés/édités avec “<-”

2.8 Utiliser des fonctions dans R

R est un langage orienté vers les objets qui sont au centre des manipulations produites. Les actions sont réalisées à l’aide de fonctions qui agissent sur des objets. Les fonctions sont déclarées par leurs noms et suivies de parenthèses : fonction(). A l’intérieur des fonctions, on déclare un ou plusieurs arguments : les objets et des options.

A <- 14.5646
round(A, digits = 2)
## [1] 14.56

round est la fonction “arrondir”, A l’objet - nécessairement numérique - à arrondir, digits = 2 l’option “2 décimales”.

Par défaut, notations anglosaxonnes (. ou décimales)

  • Objets : Liste des objets créés (tableaux avec variables, listes, etc.)

  • Historique

  • Fichiers : Dossiers et fichiers

  • Graphiques : Zoom, export

  • Aide : Obtenir plus d’information sur une fonction, par exemple la fonction table() :

?print
  • Menus :
    • Fichiers : Nouveau fichier (script, présentation), ouvrir fichier, enregistrer, fichiers récents
    • Outils : Installer package (gmodels), options
    • Session : Actions sur la session de travail

Enregistrer votre script : File > Save as… et enregistrer le script dans le sous-dossier “scripts”

2.9 Organiser son travail

Quand on entame un projet, les lignes de commande, scripts, tableaux créés et dossiers peuvent s’accumuler. Il est important d’organiser son travail dès le début.

Gérer ses projets :

On crée un dossier par projet. Ce dossier est directement relié à votre projet et comporte des sous-dossiers “data”, “output” comme nous l’avons déjà fait.

En haut à droite, une icône en forme de cube bleu permet de créer un “nouveau projet”. C’est un assistant de création d’un dossier dédié à un projet spécifique dans votre explorateur (windows, mac ou linux). Il sera associé à une session de RStudio, qui sera indépendante des documents et objets utilisés pour un autre projet.

ou bien File > New Project > Existing directory –> Browse > Sélectionnez votre dossier créé pour la formation > Create project

Un fichier Nom_du_dossier.Rproj apparaît dans le dossier, c’est le raccourci qui mènera à la session R. Un fichier .RData sera également créé et contiendra les objets présents dans l’environnement au moment de la fermeture de la session (si vous l’enregistrez).

2.10 Commentaires

Lire ou relire un programme, ce n’est pas lire un roman. Ca peut être fastidieux, surtout lorsque le programme n’est pas commenté.

Les commentaires permettent de comprendre la logique engagée sur une partie de programme, de préciser l’utilisation d’une fonction et d’organiser un script. Les commentaires sont précédés de # et ne sont pas exécutés.

Pour passer un ensemble sélectionné en commentaire (et inversement) : ctrl+shift+c.

Aérer le texte et mettre des titres facilitent aussi grandement la lecture de scripts : sur une ligne, # Titre ----

Enfin, il y a plusieurs façons d’arriver à un résultat recherché ; Il s’agit déjà de comprendre ce qu’on fait. On préferera l’écriture la plus concise et compréhensible

2.11 Présentation - En résumé

  • RStudio est une interface de développement facilitant la gestion des scripts et des projets statistiques.

    -> Le script contient l’ensemble des instructions qu’on conservera

    -> La console renvoie les retours des instructions et divers messages (informations, erreurs) ; on peut y exécuter du script qui ne sera pas enregistré

  • Les projets sont des sessions qu’on associe à un dossier :

    -> Vous retrouvez votre session : script, objets, recodages et transformations déjà effectués

    -> Renvoie directement à cet emplacement

    -> Evite de mélanger les données et scripts portant sur différents sujets

    -> Permet de partager l’ensemble du dossier

=> Veillez à :

Organiser vos différents scripts à l’aide des sections et commentaires

-> un·e futur·e vous ou un·e collègue doit pouvoir se replonger facilement dans le code

Ne laisser que le code utile ne comportant pas d’erreur ou d’instructions longues à exécuter et/ou inutile à exécuter (comme un install.packages).

-> Jouez sur les zones console (retours et tests) et script (code enregistré). Dans l’idéal, vous devriez pouvoir exécuter l’ensemble du script sans erreur (le bouton “source” exécute l’ensemble du script dans l’ordre linéaire d’affichage et s’arrête à la première erreur).

-> Pour aller plus loin : voir le “Guide des bonnes pratiques”, utilitR, Insee, https://www.pratiques.utilitr.org/index.html

3 Importer des données

3.1 Importations

On peut créer des objets en explicitant leur contenu comme on l’a fait. Mais en général, on ne saisit pas directement les données dans R, elles sont recueillies dans un fichier (contenu dans un dossier de votre ordinateur ou en ligne) qu’on importe dans R en créant un nouvel objet, en choisissant la fonction de lecture et d’importation adéquate et en indiquant l’endroit où se trouve ce fichier.

=> Le tableau est importé dans R. Ce qui signifie que toutes les opérations effectuées sur ces tableaux ne sont effectives que dans R et ne modifient pas le fichier source.

Le fichier source peut être en format :

  • Texte (.txt, .csv),
  • Tableur : Excel (xls, xlsx), Calc (.ods),
  • Tables issues de logiciels statistiques : SAS (.sas7bdat), SPSS (sav),
  • Format R : (.RData, .rds)
  • html, xml, json, etc.

Plusieurs packages facilitent l’importation directe de tableaux de données enregistrés dans divers formats (ex : package xlsx).

3.2 Importer des fichiers textes (csv, txt)

Les fichiers sont enregistrés en CSV dans le sous-dossier “data” : On indique le chemin “data/nom_fichier.csv” :

caracteristiques <-read.csv2("data/caracteristiques-2019.csv", 
                             fileEncoding = "UTF-8",
                             stringsAsFactors = F)
# argument nécessaire : "SousDossiers/NomFichier.csv"
# arguments qui peuvent être utiles :
# - fileEncoding = format d'encodage des caractères
# arguments par défaut :
# header = TRUE/FALSE : La première ligne correspond-elle aux titres des variables ?
# sep = "," : Choix du caractère séparant les cellules du tableau
# dec ="," : Choix du caractère des décimales

Note :

  • read.csv quand le séparateur est une ,
  • read.csv2 quand le séparateur est un ;
  • read.table pour les fichiers .txt et séparateur = \t

L’option stringsAsFactors = F est importante car (au moins jusqu’à la version 4 de R), la fonction d’import read.csv2 transforme par défaut les chaînes de caractères en “factors”.

Les “factors” dans R sont des colonnes d’un tableau pour lesquelles les modalités sont enregistrées sous forme de chiffres (un peu comme dans un dictionnaire des codes). La colonne genre contiendra plusieurs libellés “homme”, “femme” enregistrés sous les codes 1 et 2.

Les factors sont utiles car ils prennent moins de place et surtout leurs modalités sont ordonnés (présentation des modalités dans un graphique ou un tableau de résultats, modalité de référence pour des régressions)

Mais leur utilisation est délicate, peut mener à des erreurs et demande un peu de pratique. Par exemple, on ne peut pas directement modifier les chaînes de caractère d’un facteurs (par exemple modifier la casse des modalités) ; il faut transformer leur type.

3.3 Importer les 4 tables BAAC

-> Sur ce modèle, importez les 3 autres tables BAAC : lieux, usagers et véhicules.

lieux <-read.csv2("data/lieux-2019.csv", 
                      fileEncoding = "UTF-8",
                             stringsAsFactors = F)
vehicules <-read.csv2("data/vehicules-2019.csv", 
                      fileEncoding = "UTF-8",
                             stringsAsFactors = F)
usagers <-read.csv2("data/usagers-2019.csv", 
                    fileEncoding = "UTF-8",
                             stringsAsFactors = F)

3.4 Objet(s) R

3.4.1 Un objet R

Fichier .rds :

readRDS("my_data.rds")
ChangementDeNom <- readRDS("my_data.rds")

3.4.2 Plusieurs objets R

… Contenus dans un fichier .RData (ou .rda) :

load("data.RData") 
# Restaure un environnement (ensemble des objets)
# enregistré au préalable

3.5 Tables d’autres logiciels statistiques (sas, spss)

Pour les bases de logiciels de statistiques (sas, spss, stata) : Package {haven} :

library(haven)

# SAS
table <- read_sas("mtcars.sas7bdat")
write_sas(table, "mtcars.sas7bdat")

# Stata
table <- read_dta("mtcars.dta")
write_dta(table, "mtcars.dta")

# SPSS
table <- read_sav("mtcars.sav")
write_sav(table, "mtcars.sav")

Cf : https://github.com/tidyverse/haven

3.6 Fichiers tableurs (xls, xlsx)

Pour les fichiers excel : Package {readxl} :

library(readxl)
table <-read_excel("fichier.xlsx", sheet = 3) 
# ou read_xlsx

Fichiers dbf : avec {foreign}

library(foreign)
table <- read.dbf("mtcars.dbf", as.is = TRUE ) 
# as.is = TRUE pour modifier les variables qualitatives en factor

3.7 Exporter des données

Format R (un objet) :

saveRDS(Table, "Table.rds")
Table <- readRDS("Table.rds")

Ensemble de l’environnement :

save(table1, table2, matrice, file = "mydata.RData")
# ou
save.image("mydata.RData") 
# note : .rda est équivalent à .RData
load("mydata.RData") 
# /!\ importe l'ensemble, même si les objets 
# existent déjà

Fichier texte :

write.csv2(Table, "Table.csv",  na="", row.names = F)
write.table(Table, "Table.txt", sep="\t") 
# "clipboard" sous Windows pour copier 
# dans le presse-papiers

3.8 Importation des données - En résumé

Suivant les types des données à importer (leur extension), différentes fonctions d’importation seront utilisées :

  • Pour les fichiers texte .csv : read.csv2() (;) ou read.csv() (,) ;
  • Pour les fichiers txt : read.table()

Un package utile facilitant les importations et exportations (entre la session R et le dossier associé au projet) : rio, voir la vignette de présentation

4 Exploration des données

4.1 Premier aperçu d’une table

head(usagers, 10)
# Aperçu des 10 1ères lignes (6 par défaut)
dim(usagers) # dimension du tableau
## [1] 132977     15
names(usagers)#<< 
##  [1] "Num_Acc"     "id_vehicule" "num_veh"     "place"       "catu"       
##  [6] "grav"        "sexe"        "an_nais"     "trajet"      "secu1"      
## [11] "secu2"       "secu3"       "locp"        "actp"        "etatp"
# Nom des variables
str(usagers) 
## 'data.frame':    132977 obs. of  15 variables:
##  $ Num_Acc    : num  2.02e+11 2.02e+11 2.02e+11 2.02e+11 2.02e+11 ...
##  $ id_vehicule: chr  "138 306 524" "138 306 524" "138 306 525" "138 306 523" ...
##  $ num_veh    : chr  "B01" "B01" "A01" "A01" ...
##  $ place      : int  2 1 1 1 1 2 1 1 1 1 ...
##  $ catu       : int  2 1 1 1 1 2 1 1 1 1 ...
##  $ grav       : int  4 4 1 4 1 4 4 1 1 1 ...
##  $ sexe       : int  2 2 1 2 1 2 1 1 1 1 ...
##  $ an_nais    : int  2002 1993 1959 1994 1996 1930 1995 1966 1993 1968 ...
##  $ trajet     : int  0 5 0 0 0 9 9 1 0 5 ...
##  $ secu1      : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ secu2      : int  0 0 0 0 0 0 0 0 8 8 ...
##  $ secu3      : int  -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ...
##  $ locp       : int  -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ...
##  $ actp       : chr  " -1" " -1" " -1" " -1" ...
##  $ etatp      : int  -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ...
# Nom, type des variables et premières observations

4.2 Explorer une colonne nominale

4.2.1 Modalités uniques

unique(usagers$catu) # modalités uniques
## [1] 2 1 3
class(usagers$catu) # type de la colonne
## [1] "integer"
# n'ayant rencontré que des chiffres dans cette colonne,
# R l'interprète comme étant de type "integer" = "nombre entier"

Remarques : On pourrait vouloir modifier le type de la colonne et les valeurs affichées -> partie suivante

4.2.2 Effectifs

# Nombre d'observations pour chaque modalité :
table(usagers$sexe) 
## 
##     1     2 
## 90384 42593
# Ajout des NA : Non-attribués, sans valeur, s'il y en a :
table(lieux$v1, useNA="ifany") 
## 
##     0     2     3  <NA> 
## 47895   176    23 10746
# Ajout de l'ensemble :
addmargins(
  table(usagers$sexe, useNA="ifany")
  ) 
## 
##      1      2    Sum 
##  90384  42593 132977

4.2.3 Pourcentages

prop.table(
  table(usagers$sexe)
  )*100 # En pourcentages
## 
##        1        2 
## 67.96965 32.03035
round(
  prop.table(table(usagers$sexe))*100,
  1) # En pourcentages arrondis
## 
##  1  2 
## 68 32
library(questionr)
freq(usagers$sexe, sort="dec",total=T) 
# sort="dec" pour trier par ordre décroissant,
# cum = T pour les %ages cumulés, total= T pour avoir le total,
# valid = F pour enlever la colonne val%

# Export :
resultat <- freq(usagers$sexe, sort="dec",total=T,valid=F)
write.csv2(resultat, "output/tap_sexe.csv") 

4.2.4 Mise en pratique

-> Quelle est la répartition des catégories d’usagers parmi les personnes impliquées dans les accidents ?

freq(usagers$catu, valid=F, sort="dec", total=T)

4.3 Explorer une colonne numérique

4.3.1 Indices de centralité et de répartition

# Moyenne :
mean(usagers$an_nais, na.rm=T)
## [1] 1980.08
# Moyenne arrondie :
round(
  mean(usagers$an_nais, na.rm=T),
  digits = 0)
## [1] 1980
# Moyenne tronquée :
trunc(
  mean(usagers$an_nais, na.rm=T),
  digits = 0)
## [1] 1980
# Médiane :
median(usagers$an_nais, na.rm = T)
## [1] 1983
# Quartiles, moyenne et nombre de non-attribués
summary(usagers$an_nais)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    1900    1967    1983    1980    1995    2019
# Quantile (avec pas au choix)
quantile(usagers$an_nais, seq(0,1,.1), na.rm=T) # déciles
##   0%  10%  20%  30%  40%  50%  60%  70%  80%  90% 100% 
## 1900 1953 1963 1971 1977 1983 1989 1993 1997 2001 2019

4.4 Exploration des données - En résumé

  • Structure d’un tableau de données : names pour les noms des variables, str pour les types des colonnes

  • Premières observations d’un tableau : head(tableau) et d’une colonne ! head(tableau$variable)

  • Type d’une colonne : class(tableau$variable)

  • Effectifs et poucentages sur une variable avec freq : freq(variable)

  • Pourcentages avec prop.table, rprop et cprop s’appliquant sur une table d’effectifs : rprop(table(1èreVariable, 2èmeVariable))

  • Indices de répartition : min, max, sd, mean, median et summary.

5 Mise en forme des données

5.1 Recodages de modalités

Jusqu’ici, on dépend des choix de codage effectués par les producteurs des tables. Au fur et à mesure des explorations, certaines modifications peuvent se révéler intéressantes :

  • modifier les codes par les libellés présentés dans le dictionnaire des codes,
  • calculer l’âge au lieu d’utiliser l’année de naissance,
  • ré-typifier une colonne qui aurait été mésinterprétée pour effectuer des calculs,
  • compter le nombre de personnes impliquées pour chaque accident,
  • relier les lignes des usagers à leurs accidents respectifs, etc.

La première opération consiste à recoder les variables dont les modalités apparaissent parfois en codes, pour un gain de place, comme c’est le cas ici.

5.1.1 Recodage par assignation d’une variable nominale

Avec la syntaxe tidyverse, le recodage peut se faire terme à terme avec fct_collapse. Attention, cette fonction porte sur des variables de type factor, il faut s’assurer du type de la colonne - et éventuellement le corriger - avant :

class(usagers$sexe)
## [1] "integer"
usagers$sexe <- factor(usagers$sexe)
class(usagers$sexe)
## [1] "factor"
  • Modifier en réel entier (integer) : as.integer()

  • Modifier en réel à décimales (numeric) : as.numeric()

  • Modifier en variable binaire (logical) : as.logical()

  • Modifier en date : as.Date()

  • Modifier en chaîne de caractère (character) : as.character()

Puis recodage à l’aide du dictionnaire des codes fourni dans la documentation et de la fonction fct_collapse :

# sexe
usagers$sexe <- fct_collapse(usagers$sexe,
                           "Homme"="1",
                           "Femme"="2")

Il est possible de condenser ces deux opérations : Exemple avec le recodage de la colonne grav :

# grav
usagers$grav <- fct_collapse(factor(usagers$grav),
                                 "Indemne"="1",
                                 "Tué" ="2",
                                 "Blessé hospitalisé"="3",
                                 "Blessé léger"="4")
levels(usagers$grav)
## [1] "Indemne"            "Tué"                "Blessé hospitalisé"
## [4] "Blessé léger"
# levels() nous donne les différentes modalités

=> De la même façon, recodez les variables catu et traj

5.1.1.1 Recodage des variables catu et traj

# catu
usagers$catu  <- fct_collapse(factor(usagers$catu),
                              "Piéton" = "3",
                              "Conducteur"="1",
                              "Passager"="2")

# traj
usagers$trajet <- fct_collapse(factor(usagers$trajet),
                                 "Domicile/travail ou école"=c("1","2"),#<<
                                 "Courses/achats"="3",
                                 "Utilisation professionnelle"="4",
                                 "Promenade/loisirs"="5",
                                 "Autre"="9",
                               "NR"=c("0","-1"))
# fct_collapse permet de recoder 2 valeurs en une unique
levels(usagers$trajet)
## [1] "NR"                          "Domicile/travail ou école"  
## [3] "Courses/achats"              "Utilisation professionnelle"
## [5] "Promenade/loisirs"           "Autre"

=> Recodez les variables lum, agg et atm de la table “caractéristiques”

5.1.1.2 Recodages de la table Caractéristiques

# Luminosité
caracteristiques$lum <- fct_collapse(factor(caracteristiques$lum),
                           "Jour"="1",
                           "Aube/crépuscule"="2",
                           "Nuit (sans écl.)"=c("3","4"),
                           "Nuit (avec écl.)"="5")
# Agglomération
caracteristiques$agg <- fct_recode(factor(caracteristiques$agg),
                           "Hors agglo."="1",
                           "En agglo."="2")
# Conditions atmosphériques
caracteristiques$atm <- fct_recode(factor(caracteristiques$atm),
                         "Normales"="1",
                         "Pluie légère"="2",
                         "Pluie forte" ="3",
                         "Neige, grêle"="4",
                         "Brouillard"="5",
                         "Vent fort, tempête"="6",
                         "Temps éblouissant"="7",
                         "Temps couvert"="8",
                         "Autre" = "9")

5.1.2 Calculs sur les variables

# /!\ 2 valeurs "aberrantes" :
usagers$an_nais <- na_if(usagers$an_nais,1900)
usagers$an_nais <- na_if(usagers$an_nais,1901)

na_if transforme une modalité en NA = non-attribué. Les valeurs NA sont spécifiques. is.na() permet de les mettre en évidence :

is.na(c(NA, "NA"))
## [1]  TRUE FALSE

Calcul de l’âge à partir de l’année de naissance :

usagers$age <- 2019 - as.integer(usagers$an_nais)

- soustraction, + addition, / division, * multiplication…

5.1.3 Création de catégories

# Selon une séquence définie :
seq(0,10,1)
##  [1]  0  1  2  3  4  5  6  7  8  9 10
# = séquence allant de 0 a 10 avec un pas de 1
usagers$age_classe <- cut(usagers$age, seq(0,110,10), 
                                    right=F)#<< 
# right = F permet de borner à l'inférieur et non au supérieur

5.1.4 Recodages conditionnels : créer de nouvelles variables à partir de celles existantes

2 fonctions principales permettent de recoder des variables sur conditions :

  • ifelse(condition, si condition remplie, si condition non remplie) :

Créer une variable qui distingue les accidents ayant eu lieu dans les Hauts-de-France :

caracteristiques$HdF <- ifelse (caracteristiques$dep %in% c("59","62","80","60","2"), # condition
                      "Hauts de France", # Valeur si condition remplie
                      "Hors Hauts de France") # Valeur si non
freq(caracteristiques$HdF)
  • case_when( conditions 1 ~ effet de la condition 1 , condition 2 ~ effet de la condition 2 ,etc, TRUE ~ effet si aucune condition n'est remplie)

Permet d’enchaîner plusieurs conditions à la suite. Exemple avec l’heure à laquelle a eu lieu l’accident :

# A quoi ressemblent les valeurs ?
head(caracteristiques$hrmn)
## [1] "01:30" "02:50" "15:15" "20:20" "04:00" "14:03"

Proposition : une fois supprimés les “:”, on transforme la colonne en type numérique

caracteristiques$hrmn <- gsub(":","",caracteristiques$hrmn)

caracteristiques$hrmn <- as.numeric(caracteristiques$hrmn)

# Puis, on applique des conditions pour distinguer différentes tranches horaires ;

caracteristiques$hrmnCl <- case_when(caracteristiques$hrmn < 600 ~ "00h-05h59",
                          caracteristiques$hrmn < 1000 ~ "06h-09h59",
                          caracteristiques$hrmn < 1400 ~ "10h-13h59",
                          caracteristiques$hrmn < 1700 ~ "14h-16h59",
                          caracteristiques$hrmn < 2000 ~ "17h-19h59",
                          caracteristiques$hrmn < 2400 ~ "20h-23h59",
                          T ~ "")

5.1.4.1 Utiliser les conditions

Opérateurs utiles :

  • == : Egalité (A == B signifie “A est égal à B”)
  • != : Exclusion ( A != B signifie “A est différent de B”)
  • < , > , <= , >= : inférieur, supérieur, inférieur ou égal, supérieur à égal
  • %in% : appartient à

Enchaînements de plusieurs conditions :

  • : Ou bien
  • & : Et

5.1.5 Exercice : Recodez la catégorie de véhicule de la table Véhicules

Les modalités pourront être : non-motorisé, 2-roues motorisées, voiture, poids lourd/trains

# freq(vehicules$catv)
vehicules$catv_rec <- case_when(vehicules$catv %in% c(1,50,60,80) ~ "Non-motorisé",
                                vehicules$catv %in% c(2,3,30:36,41:43) ~ "2-roues motorisées, voiturette",
                                vehicules$catv %in% c(7,10) ~ "Voiture",
                                vehicules$catv %in% c(13:21,37:40) ~ "Poids lourd, train",
                                T ~ "NR")
freq(vehicules$catv_rec, sort="dec",valid=F, total=T)

5.2 Sélections, filtres et tris

Suivant ce qu’on recherche, on peut souhaiter ne conserver que certaines colonnes ou lignes d’un tableau (lorsqu’on s’intéresse à une sous-population par exemple).

5.2.1 Sélection de colonnes select

 # Sélections de colonnes relatives aux dates,
# dans la table caracteristiques :
Date <- select(caracteristiques, Num_Acc, mois, jour, hrmn)

avec caracteristiques (tableau de données) en 1er argument puis les colonnes qu’on souhaite conserver séparées par une “,”. C’est une syntaxe caractéristique de {tydiverse}.

5.2.2 Sélection de lignes par position : slice

# 4 premières lignes :
slice(usagers,1:4) 

5.2.3 Sélection de lignes par conditions, ou filtres : filter

usagersPietons <- filter(usagers, catu=="Piéton")

la table usagersPietons ne contient plus que les lignes concernant les piétons.

5.2.4 Trier des données : arrange

usagers <- arrange(usagers, desc(age))
# desc() pour trier par ordre décroissant

5.2.5 Mise en pratique

-> A l’aide des fonctions que nous venons de voir, présentez l’âge, la gravité de l’accident et la catégorie d’usagers des 2 hommes les plus âgés qu’on retrouve dans les données BAAC 2019.

Plusieurs solutions :

On peut encaster les fonctions ou les écrire à la suite.

slice(
  select(
    arrange(
      filter(
        usagers, # Table de départ
        sexe=="Homme"), # condition du filter
      desc(age)), # tri de l'arrange
    age, grav, catu), # colonnes du select
  1:2) # lignes du slice

… il faut lire de l’intérieur vers l’extérieur, difficile de voir les arguments associés à chaque fonction.

Ou bien

exo <- filter(usagers, sexe=="Homme")
exo <- arrange(exo, desc(age))
exo <- select(exo, age, grav, catu)
exo <- slice(exo, 1:2)
exo

Création d’un objet intermédiaire qui n’est pas si nécessaire.

Un opérateur rend plus lisibles les enchainements de ce type

5.3 L’opérateur %>% (pipe)

L’opérateur %>% (pipe, ctrl+shift+m) permet d’enchainer les fonctions en prenant dans chaque fonction le résultat de la fonction précédente comme argument principal : f(a) s’écrit a %>% f() ; Ce qui est à gauche de %>% est basculé en premier argument de ce qui suit l’opérateur.

table %>% fonction1() %>% fonction2()

au lieu de fonction2(fonction1(table))

Ce qui, pour l’exemple, donne :

usagers %>% 
  filter(sexe=="Homme") %>% 
  arrange(desc(age)) %>% 
  select(age, grav, catu) %>% 
  slice(1:2)

5.4 Mise en forme des données - En résumé

5.4.0.1 Recodage de variable nominale pas assignation

  • Transformer la colonne en type factor :
usagers$grav <- factor(usagers$grav)
  • Recoder terme à terme avec fct_collapse :
usagers$grav <- fct_collapse(usagers$grav,
                                 "Indemne"="1",
                                 "Tué" ="2",
                                 "Blessé hospitalisé"="3",
                                 "Blessé léger"="4")
  • Sortir les modalités recodées avec levels
levels(usagers$grav)
## [1] "Indemne"            "Tué"                "Blessé hospitalisé"
## [4] "Blessé léger"

5.4.0.2 Recodages conditionnels : créer de nouvelles variables à partir de celles existantes

2 fonctions principales permettent de recoder des variables sur conditions :

  • ifelse(condition, si condition remplie, si condition non remplie) :

  • case_when( conditions 1 ~ effet de la condition 1 , condition 2 ~ effet de la condition 2, etc, TRUE ~ effet si aucune condition n'est remplie)

5.4.0.3 Sélections, filtres et tris

Les principales fonctions permettant de réarranger les tables via tydiverse sont :

  • select(table, colonnes à conserver) : Sélection de colonnes

  • filter(table, condition du filtre) : Sélection de lignes

  • arrange(table, colonnes sur laquelle faire le tri, desc(2ème colonne sur laquelle faire un tri décroissant)) : Tri de la table

  • slice(table, position des lignes à conserver) : Sélection de lignes selon leur position

  • L’opérateur %>% (pipe, ctrl+shift+m) permet d’enchaîner des fonctions : f(a) s’écrit a %>% f().

6 Opérations sur les tables

6.1 Regroupements de lignes

Il peut être intéressant de regrouper plusieurs observations selon un ou plusieurs critères afin de produire des calculs. La fonction group_by produit ces regroupements et est nécessairement associée à une fonction de calcul dans summarise.

6.1.1 Exemple 1 : Compter le nombre d’usagers moyen par accident

NbUsagers <- usagers %>% 
  group_by(Num_Acc) %>% #<<
  summarise(NbUsagers = n()) #<<
# n() compte le nombre de lignes
mean(NbUsagers$NbUsagers)
## [1] 2.259976

6.2 Mise en pratique : Exemple 2

-> De la même façon, quel est le nombre maximum de véhicules impliqués dans un même accident ?

NbVehicules <- vehicules %>% 
  group_by(Num_Acc) %>% 
  summarise(NbVehicules = n())

max(NbVehicules$NbVehicules)
## [1] 12

6.2.1 Exemple 3 : Moyenne d’âge et nombre de personnes impliquées par accident

En ne présentant que les 6 premières observations :

usagers %>% 
  group_by(Num_Acc) %>% 
  summarise(AgeMoy = mean(age),
            NbPers = n()) %>% 
  head(6) # pour ne sortir que les 6 premières observations

6.3 Jointures de tables

Les données sur les accidents sont organisées en plusieurs tables relatives à plusieurs unités statistiques (l’événement “accident” des tables caractéristiques et lieux, les véhicules impliqués et les usagers impliqués).

On remarque d’ailleurs que le nombre d’observations pour les tables de chaque type d’unité varie. Il est toutefois possible de les regrouper si on dispose d’une clé d’appariemment ou variable de jointure (une variable commune à deux tables permettant d’associer les accidents avec les personnes et les véhicules concernés).

6.3.1 Exemple 1 : Jointure des tables “Caractéristiques” et “lieux” :

Pas de problème d’unité puisque c’est la même :

Accident <- left_join(x = caracteristiques, y = lieux, by = "Num_Acc")

Les 2 tables ont le même nombre de lignes et les identifiants “Num_Acc” sont uniques (un numéro n’apparait qu’une fois dans chacune des tables). left_join “envoie” les données de la table y dans la table x en associant les lignes ayant le même “Num_Acc”.

6.3.2 Exemple 2 : Ajout des caractéristiques de l’accident dans la table usagers

En revanche, ici, il faut faire un choix car plusieurs usagers peuvent être concernés par un même accident. On peut ajouter les informations de l’accident à la table usagers et non l’inverse.

usagers <- left_join(x = usagers, y = Accident, by = "Num_Acc")

L’écriture est la même mais le choix de l’ordre de déclaration des tables compte : On a bien conservé l’unité “usagers” dans laquelle on a “injecté” les informations relatives aux accidents respectifs. Concrètement, un même accident apparait sur autant de lignes qu’il y a eu d’usagers impliqués.

6.3.3 Précisions

Attention, on ne peut joindre que 2 tables à la fois.

les fonctions join : Nous avons vu la fonction left_join, il existe aussi :

  • right_join : Ajout des informations de la table x vers la table y
  • inner_join : Conserve les lignes présentes dans les deux tables
  • full_join : Conserve l’ensemble des lignes des deux tables
  • anti_join : Conserver les lignes qui ne se retrouvent que dans une des deux tables
  • by = c("a" = "b") : Si les noms des colonnes sont différents dans les deux tables
  • by = c("a1" = "a2", "b1" = "b2") : Si plusieurs colonnes de jointure avec des noms différents

6.4 Opérations sur les tables - En résumé

La fonction group_by permet de produire des regroupements et est associée à une fonction de calcul dans summarise.

Pour joindre des tables (et produire des calculs sur des colonnes issues de 2 tables différentes), il faut :

  • Les noms des tables
  • Le ou les noms de la ou des colonnes d’appariemment (clés de jointure)
  • Identifier les unités statistiques des tables et décider de la table ou des tables dont on conservera la/les structure(s)

Voir la cheatsheet sur dplyr et tidyr : https://thinkr.fr/pdf/dplyr-french-cheatsheet.pdf

7 … Poursuivre l’exploration des données

7.1 Croiser deux variables nominales

# Effectifs :
addmargins(table(usagers$sexe, usagers$catu))
##        
##         Conducteur Passager Piéton    Sum
##   Homme      72607    12116   5661  90384
##   Femme      24749    12240   5604  42593
##   Sum        97356    24356  11265 132977
# Pourcentages :

prop.table(table(usagers$sexe, usagers$catu),1) # 2 en colonnes
##        
##         Conducteur   Passager     Piéton
##   Homme 0.80331696 0.13405027 0.06263277
##   Femme 0.58105792 0.28737116 0.13157092
# Arrondi :
round(
  prop.table(table(usagers$sexe, usagers$catu),1)*100,
  1)
##        
##         Conducteur Passager Piéton
##   Homme       80.3     13.4    6.3
##   Femme       58.1     28.7   13.2
# avec questionr :
rprop(table(usagers$sexe, usagers$catu)) 
##           
##            Conducteur Passager Piéton Total
##   Homme     80.3       13.4      6.3  100.0
##   Femme     58.1       28.7     13.2  100.0
##   Ensemble  73.2       18.3      8.5  100.0
# cprop en colonnes et prop pour les pourcentages totaux

7.1.0.1 Mise en pratique

  • Quelle est la gravité des accidents pour les piétons selon l’heure de la journée ?
Pietons <- usagers %>% filter(catu=="Piéton")
rprop(table(Pietons$hrmnCl, Pietons$grav))
##            
##             Indemne Tué   Blessé hospitalisé Blessé léger Total
##   00h-05h59   3.3    17.0  33.3               46.4        100.0
##   06h-09h59   2.3     4.8  29.1               63.8        100.0
##   10h-13h59   2.4     4.0  29.0               64.6        100.0
##   14h-16h59   3.4     3.7  27.8               65.2        100.0
##   17h-19h59   3.1     3.4  28.3               65.3        100.0
##   20h-23h59   3.3     7.0  28.0               61.8        100.0
##   Ensemble    2.9     4.7  28.7               63.7        100.0

7.2 Croiser une variable numérique et une nominale

…en utilisant group_by et summarise :

usagers %>% 
  group_by(catu) %>% 
  summarise(min = min(age, na.rm = T),
            max = max(age, na.rm = T),
            mean = round(mean(age, na.rm = T), 1),
            mediane = median(age, na.rm = T))

7.3 Mise en pratique

-> Quel est l’âge médian des conducteur·rices selon le type de trajet qu’ils et elles effectuaient au moment de l’accident ?

usagers %>% 
  filter(catu=="Conducteur") %>% 
  group_by(trajet) %>% 
  summarise(AgeMedian = median(age, na.rm=T)) %>% 
  arrange(AgeMedian)

8 Ressources

R généralités :

Cheat Sheet : https://www.rstudio.com/resources/cheatsheets/

Aides en ligne et sites ressources :

Quelques # et @ twitter “actifs” :

  • #rstats

  • #rstatsFR

  • @icymi_r

  • @rgeomatic

  • @hadleywickham

  • @thinkR_fr