Gestion et Traitement des Données

Application sous R-Studio

M.SANAA, D.CUZZUCOLI et F.AUDIAT-PERRIN

\rule{\linewidth}{1.5pt} \hspace{10cm}

ANCSEP
Appui institutionnel en matière de maîtrise des risques sanitaires et environnementaux TN/14/ENP/HE/44

ATELIER DE FORMATION GESTION ET TRAITEMENT DES DONNEES EN EVALUATION DU RISQUE

Tunis 3-6 janvier 2017

\newpage

Page vide

\newpage

\newpage

M. SANAA1 Les data.frames sont des tableaux à deux dimensions. Leur particularité est de pouvoir stocker des données hétérogènes selon les colonnes. C’est le type d’objet que vous utiliserez le plus dans R., D. CUZZUCOLI et F. AUDIAT-PERRIN

1 Introduction

Ce polycopié aborde la gestion et le traitement des données scientifiques dans le cadre d’une évaluation du risque. Vous apprendrez à intégrer vos données dans R, à les avoir dans la structure la plus utile, à les transformer, à les visualiser et à les modéliser. Il s’agit d’acquérir les bonnes pratiques pour une meilleure utilisation des données scientifiques. Vous apprendrez à écrire des procédures R qui assurent la traçabilité, la reproductibilité des analyses des données et aussi un gain de temps considérable par comparaison aux analyses faites sur des outils communs (exemple Excel).

Il s’agit d’appliquer la science des données (en anglais “data science”) qui est une discipline qui s’appuie sur des outils mathématiques, statistiques, informatiques et de visualisation des données. Elle vous permettra de transformer vos données brutes en informations et connaissances. L’objectif de cette formation est de vous aider à apprendre les outils les plus importants dans R qui vous permettent de faire de la science des données. A la fin de cette formation vous aurez les outils pour relever un large éventail de défis liés à la science des données, en utilisant les meilleures parties de R.
Un projet typique de science de données comprend les étapes suivantes:

Science des données

Science des données

Vous devez tout d’abord importer vos données dans R. ce qui implique en général que vous avez des données stockées dans un fichier ou dans une base de données et que vous les chargez dans un data.frame2 (http://www.r-project.org/) de R.
Une fois vos données importées, il convient de les ranger. Le rangement des données dans un tableau suppose que chaque colonne est une variable, et chaque ligne est une observation. Le choix de la structure du rangement des données doit être en cohérence avec les traitements souhaités des données.
Une fois que vous avez des données rangées, une première étape commune est de les transformer. La transformation inclut la sélection des observations d’intérêt (comme toutes les personnes d’une ville ou toutes les données de l’année dernière), la création de nouvelles variables qui sont des fonctions de variables existantes et le calcul d’un ensemble de résumé statistiques (comme les comptages ou les moyennes). Une fois que vous avez des données bien rangées avec les variables qu’il faut, vous disposez de deux approches complémentaires pour comprendre les phénomènes étudiés: la visualisation et la modélisation.

2 R, RStudio et R Packages

R est un langage et un environnement puissants pour les calculs statistiques et les graphiques. C’est un projet du domaine public. Les principaux avantages de R sont sa gratuité et la disponibilité d’aide en ligne. Il est assez similaire à d’autres programmes tels que MatLab (non gratuit), mais plus convivial que les langages de programmation comme C ++ ou Fortran. Vous pouvez utiliser directement R, mais pour des fins pédagogiques, nous préférons utiliser R avec l’interface RStudio (également gratuite). En plus de R et RStudio, nous utiliserons plusieurs packages qui doivent être installés et chargés séparément.

2.1 Installer R

Pour installer R, allez sur le site web de R3 http://www.rstudio.org/ et suivez les étapes suivante:

2.2 Intaller RStudio

Pour installer RStudio, allez sur le site web de RStudio4 La fonction ‘seq’ sert à générer des suites de nombres, ici seq(from = 0, to = 80, by = 5): 0, 5, 10, 15, …, 80. et téléchargez la version de votre système d’exploitation. Exécutez le fichier télécharger et répondez à toutes les questions (réponses par défaut).

Une fois que vous avez lancé RStudio vous verrez l’interface suivante. L’interface RStudio est composée de différents panneaux, dont l’arrangement peut être reconfiguré, incluant une console, un navigateur de fichiers et graphiques, l’espace de travail et l’historique des commandes :

Interface de RStudio

Interface de RStudio

2.3 Installer les packages

Un grand nombre de fonctions, contenus dans différents packages, sont installés dans la version de base du logiciel R. Il est possible (et nous en aurons besoin dans les différents cours de Statistique) d’installer des packages supplémentaires. Pour cela, lorsque vous disposez d’une connexion internet, il suffit d’utiliser la commande install.packages("nom du package") en indiquant le nom du package que l’on veut installer ou utilser le menu Tools. Il faudra ensuite charger le package à l’aide de la commande library("nom du package") ou à partir du panneau package.

3 Importation de données et manipulation de variables

Pour commencer à découvrir les fonctionalités de R nous allons utiliser deux fichiers de données conso.csv et indiv.csv. Le chargement de ces fichiers se fait à l’aide de la commande read.csv2(), qui permet de lire des fichiers CSV pour lesquels le séparateur de champ est un point-virgule, et le séparateur décimal une virgule. Les données seront associées aux objets conso et indiv à l’aide de l’opérateur =. Dans ce qui suit, nous supposerons que vous avez bien défini le dossier contenant les fichiers xxx.csv comme dossier de travail, soit à l’aide de la commande setwd() soit via le menu de RStudio (Session/Set Woking directory). Avant de commencer, il est préférable que vous listiez les objets déja présent dans votre environnement de travail et les supprimer (à l’aide de la commande rm() afin d’éviter toute confusion entre les objets de cette session avec ceux des anciennes sessions.

indiv=read.csv2("indiv.csv")

3.1 Tableau de données

Les données sont généralement représentées sous la forme d’un tableau rectangulaire dans lequel les variables sont arrangées en colonnes, et les observations en lignes. Sous R, il s’agit de data frame. Une fois que les données sont importées, l’objet indiv sera disponible dans l’environnement de travail, comme on pourra le vérifier avec la commande ls(). Les dimensions du tableau de données peuvent être vérifiées à l’aide de dim(), et la commande names() renvoit le nom des variables.

Visualisation du dossier de travail et de l’environnement de travail. Les fichiers csv sont accessibles via le panneau Files et les objets crées via le panneau Environment

Visualisation du dossier de travail et de l’environnement de travail. Les fichiers csv sont accessibles via le panneau Files et les objets crées via le panneau Environment

ls()
## [1] "indiv"
dim(indiv)
## [1] 4079   11
names(indiv)
##  [1] "cod_com" "agglo9"  "loc_log" "nomen"   "sexe_ps" "region"  "ech"    
##  [8] "v2_age"  "tage"    "poidsm"  "taillem"

La commande str() fournit un résumé de l’ensemble des variables avec leur type (ou mode de représentation) – int pour les variables numériques, factor pour les variables catégorielles – et un aperçu des 10 premières observations.

str(indiv)
## 'data.frame':    4079 obs. of  11 variables:
##  $ cod_com: int  77239 77239 78291 78003 78003 91200 91200 77143 75102 75102 ...
##  $ agglo9 : Factor w/ 9 levels "> 200 000 hab. ",..: 9 9 9 4 4 6 6 7 8 8 ...
##  $ loc_log: Factor w/ 4 levels "bourg ou village ",..: 1 1 1 1 1 2 2 1 2 2 ...
##  $ nomen  : int  110006 110007 110020 110021 110025 110034 110046 110057 110067 110071 ...
##  $ sexe_ps: Factor w/ 2 levels "femme ","homme ": 1 2 1 1 1 1 2 2 2 1 ...
##  $ region : Factor w/ 21 levels "Alsace ","Aquitaine ",..: 20 20 20 20 20 20 20 20 20 20 ...
##  $ ech    : Factor w/ 2 levels "adultes ","enfants ": 1 1 1 1 1 1 1 1 1 1 ...
##  $ v2_age : int  54 70 43 75 39 61 76 52 38 32 ...
##  $ tage   : Factor w/ 8 levels "11-14 ans ","15-17 ans ",..: 7 8 6 8 6 7 8 7 6 4 ...
##  $ poidsm : Factor w/ 428 levels "10","100","100.300003051758",..: 367 302 419 210 230 210 286 367 324 233 ...
##  $ taillem: int  162 170 170 152 165 152 163 175 181 173 ...

Une autre commande utile pour vérifier la structure des données est summary() qui fournit un résumé descriptif univarié pour chaque variable. Dans le cas des variables numériques, R indique les principaux indicateurs de tendance centrale (moyenne et médiane) et de dispersion (étendue, intervalle inter-quartile), ainsi que le nombre de valeurs manquantes représentées par le symbole NA. Dans le cas des variables catégorielles, R fournit un tableau d’effectifs, c’est-à-dire le nombre d’observations associées à chacune des modalités de la variable.

summary(indiv)
##     cod_com                          agglo9   
##  Min.   : 1053   rural                  :986  
##  1st Qu.:33281   > 200 000 hab.         :773  
##  Median :59299   100 000 à 200 000 hab. :609  
##  Mean   :54810   agglo paris            :535  
##  3rd Qu.:76627   50 000 à 100 000 hab.  :324  
##  Max.   :95637   2 000 à 5 000 hab.     :267  
##                  (Other)                :585  
##                    loc_log         nomen          sexe_ps    
##  bourg ou village      :1047   Min.   :110006   femme :2304  
##  centre ville          :1148   1st Qu.:115313   homme :1775  
##  habitat dispersé      : 446   Median :171728                
##  quartier périphérique :1438   Mean   :175486                
##                                3rd Qu.:241547                
##                                Max.   :267394                
##                                                              
##                    region           ech           v2_age     
##  Région Parisienne    : 601   adultes :2624   Min.   : 3.00  
##  Rhône-Alpes          : 343   enfants :1455   1st Qu.:14.00  
##  Languedoc            : 254                   Median :32.00  
##  Aquitaine            : 244                   Mean   :33.51  
##  Nord                 : 227                   3rd Qu.:51.00  
##  Provence Côte D'azur : 227                   Max.   :79.00  
##  (Other)              :2183                                  
##          tage         poidsm        taillem     
##  35-49 ans :837   60     :  92   Min.   : 86.0  
##  50-64 ans :750   65     :  90   1st Qu.:155.0  
##  3-10 ans  :574   58     :  84   Median :164.0  
##  11-14 ans :456   62     :  82   Mean   :159.9  
##  25-34 ans :432   63     :  79   3rd Qu.:172.0  
##  15-17 ans :425   (Other):3325   Max.   :202.0  
##  (Other)   :605   NA's   : 327   NA's   :326

Pour afficher l’ensemble des observations recueillies pour une variable données, vous taperez le nom de cette variable préfixé du nom du data frame suivi du signe $. L’expression indiv$v2_age désignera ainsi les valeurs prises par la variable v2_age dans le data frame indiv. Plutôt que d’afficher l’ensemble des valeurs, on peut vouloir limiter l’affichage à certaines observations, que l’on désignera par leur numéro. On peut ainsi choisir d’afficher, la première, les deux premières, ou la première et la dixième observation à l’aide des instructions suivantes :

indiv$v2_age[1]
## [1] 54
indiv$v2_age[c(1,2)]
## [1] 54 70
indiv$v2_age[c(1,10)]
## [1] 54 32

Il est également possible d’afficher un ensemble d’observations consécutives en utilisant la notation [i:j] où i et j désignent, respectivement, le premier et le dernier numéro d’observation. Pour afficher les 5 premières observations, on utilisera donc la commande :

indiv$v2_age[1:5]
## [1] 54 70 43 75 39

En fait, il existe une commande, head(), qui permet d’afficher les premières observations d’une variable. Par défaut, head() affichera les 6 premières observations, comme on pourra le vérifier dans l’aide en ligne. Cette valeur par défaut peut être modifiée en ajoutant l’option n=20, par exemple.

La commande summary() fonctionne également avec une variable et fournit, comme dans le cas d’un data frame, un résumé numérique de la distribution de la variable selon son type.

summary(indiv$taillem)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##    86.0   155.0   164.0   159.9   172.0   202.0     326

En plus des résumés statistiques la commande summary() renseigne le nombre de données manquantes (NA’s) pour la variable taille. Le minimum observé peut être obtenu avec la commande min(). Or dans le cas précis de la variable taille, la commande renvoie la valeur NA. Pour contourner ce problème, vous devez indiquer explicitement à R ce que vous souhaitez faire des valeurs manquantes. Par défaut, R ne supprime pas les valeurs manquantes, comme vous pouvez le vérifier dans l’aide en ligne (na.rm=FALSE), et se contente de renvoyer la valeur NA pour signaler à l’utilisateur que certaines données sont manquantes. Pour supprimer les données manquantes utilisez l’argument (na.rm=TRUE).

min(indiv$taillem)
## [1] NA
min(indiv$taillem,na.rm=TRUE)
## [1] 86

L’étendue des valeurs observées s’obtient avec range() qui, contrairement à min(), est une commande qui renvoie des résultats multiples (dans ce cas, le minimum et le maximum de la variable).

range(indiv$v2_age, na.rm=TRUE)
## [1]  3 79
range(indiv$taillem, na.rm=TRUE)
## [1]  86 202

3.2 Variables qualitatives

En général les variables qualitatives sont codées en facteur (factor). Pour connaître les différente modalité d’une variable qualitative, utilisez la commande unique. Pour déterminer le nombre d’individus par modalité, utilisez la commande table().

unique(indiv$loc_log)
## [1] bourg ou village       centre ville           quartier périphérique 
## [4] habitat dispersé      
## 4 Levels: bourg ou village  centre ville  ... quartier périphérique
unique(indiv$sexe_ps)
## [1] femme  homme 
## Levels: femme  homme
table(indiv$sexe_ps)
## 
## femme  homme  
##   2304   1775

Il est parfois utile de recoder en variable qualitative des variables continues à l’origine. Par exemple, avec la variable age, il serait tout à fait possible de créer une variable age.cat avec des classes d’amplitudes égales à 5 ans à l’aide de la commande cut(). Les limites des classes sont renseignées avec breaks=seq(0,80,5)5 La fonction paste() est utilisée pour récupérer les vraies valeurs et non pas leurs classes

indiv$age.cat=cut(indiv$v2_age, breaks=seq(0,80,5))
table(indiv$age.cat)
## 
##   (0,5]  (5,10] (10,15] (15,20] (20,25] (25,30] (30,35] (35,40] (40,45] 
##     163     411     585     405     191     194     251     304     280 
## (45,50] (50,55] (55,60] (60,65] (65,70] (70,75] (75,80] 
##     250     293     260     174     139     113      66

Si vous cherchez à créer une variable age.cat2 à 4 classes d’effectifs équilibrés, utilisez la commande quantile() qui permet de générer un quartilage de la variable. Il est important de préciser l’option include.lowest=TRUE qui permettra d’inclure l’observation dont l’âge vaut l’âge minimal, puisque par défaut les intervalles ont des bornes ouvertes (c’est-à-dire n’incluant pas) à gauche. Exemple :

indiv$age.cat2=cut(indiv$v2_age,breaks=quantile(indiv$v2_age),include.lowest=TRUE)
table(indiv$age.cat2)
## 
##  [3,14] (14,32] (32,51] (51,79] 
##    1030    1010    1059     980

3.3 Erreur de format

Il arrive souvent lors d’importation de données dans R que certaines variables n’aient pas le format adéquat. Dans le cas précis, nous avons remarqué que la variable poids a été interprétée comme variable qualitative (Factor). Il est possible de transformer cette variable en numérique à l’aide de la fonction as.numeric() et paste()6 Pour créer une fonction on utilse la structure suivante: nomdemafonction=function(variable1,variable2…) {ici on met le contenu de la fonction…}

indiv$poids=as.numeric(paste(indiv$poidsm))
summary(indiv$poids)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##   10.00   48.00   61.00   59.79   73.00  171.00     327

3.4 Sauvegarde des données

Il est conseillé de sauvegarder vos données au format RData, qui est un format propre au logiciel R. Cela facilite l’archivage de résultats intermédiaires ou l’enregistrement d’un tableau de données nettoyé (recodage de valeurs manquantes ou modalités de variables qualitative, correction des erreurs de saisie, etc.) ou augmenté de variables auxiliaires. Pour cela, vous utiliserez la commande save(). La commande load() permet quant à elle de recharger des données sauvegardées au format RData. L’extension du ficher peut être indifféremment RData ou rda.

save(indiv,file ="indiv.rda")

3.5 Enregistrement des commandes

Les commandes entrées dans le panneau Console sont immédiatement exécutées par R. Il est, cependant, conseillé de les enregistrer directement dans un script de commandes R, ce qui permet de reproduire les analyses ultérieurement. Dans l’éditeur de RStudio, il suffit d’écrire les commandes telles que vous les entrerez sous la console et il est possible d’exécuter directement la ligne sur laquelle le curseur se situe ou une sélection multiple à la console en cliquant sur le bouton RUN. Une fois enregistrées dans un fichier script R (extension .r ou .R), il est possible d’exécuter l’ensemble des instructions à l’aide de la commande source(). Attention, dans ce cas, R n’affiche pas nécessairement l’intégralité des résultats qui sont affichés en mode interactif, à moins d’ajouter l’option echo=TRUE.

4 Indexation des données et création de graphiques simples

4.1 Sélection et indexation d’observations

Pour accéder à une variable contenue dans un data frame, on utilise son nom préfixé du symbole $ et du nom du data frame.

head(indiv$v2_age)
## [1] 54 70 43 75 39 61

Une commande équivalente consiste à utiliser le numéro de position de la variable parmi les colonnes du data frame (ici, la variable v2_age se trouve dans la huitième colonne) ou d’utiliser le nom de la variable (entre quotes): indiv[,8] ou indiv[,“v2_age”].

Considérons la variable loc_log qui indique le type de commune où habitent les répondants. Si seulement un sous-groupe des répondants vous intéresse, par exemple ceux qui habite en centre ville, vous pouvez utiliser un filtre logique avec l’opérateur == (égalité logique) pour sélectionner les observations remplissant cette condition. On pourra dresser un tableau d’effectifs en utilisant le même principe via table().

head(indiv$loc_log == "centre ville ")
## [1] FALSE FALSE FALSE FALSE FALSE  TRUE
# j'ai ajouté un espace à la fin de centre ville 
#car celui qui a saisi les données avait fait de même!!
table(indiv$loc_log == "centre ville ")
## 
## FALSE  TRUE 
##  2931  1148

La commande which() permet de renvoyer les numéros d’observations (lignes du tableau) remplissant la condition.

head(which(indiv$loc_log == "centre ville "))
## [1]  6  7  9 10 11 12

Une telle instruction peut être utilisée pour indexer les observations d’une autre variable, par exemple l’âge des personnes habitant en centre ville:

head(indiv$v2_age[which(indiv$loc_log == "centre ville ")])
## [1] 61 76 38 32 69 29

Toutefois, R offre une commande plus intéressante qui permet de sélectionner à la fois des observations remplissant une ou plusieurs conditions, et un sous-ensemble de variables. Il s’agit de la commande subset() qui prend comme premier argument le nom du data frame sur lequel on souhaite opérer, comme deuxième argument un ou plusieurs filtres logiques à appliquer aux lignes, et comme troisième argument le numéro ou le nom des variables à sélectionner.

selection=subset(indiv,loc_log=="centre ville ")
head(selection)
##    cod_com               agglo9       loc_log  nomen sexe_ps
## 6    91200 5 000 à 10 000 hab.  centre ville  110034  femme 
## 7    91200 5 000 à 10 000 hab.  centre ville  110046  homme 
## 9    75102         agglo paris  centre ville  110067  homme 
## 10   75102         agglo paris  centre ville  110071  femme 
## 11   75105         agglo paris  centre ville  110081  homme 
## 12   75110         agglo paris  centre ville  110110  femme 
##                region      ech v2_age         tage poidsm taillem age.cat
## 6  Région Parisienne  adultes      61   50-64 ans      53     152 (60,65]
## 7  Région Parisienne  adultes      76 65 ans et +    66.5     163 (75,80]
## 9  Région Parisienne  adultes      38   35-49 ans      73     181 (35,40]
## 10 Région Parisienne  adultes      32   25-34 ans      58     173 (30,35]
## 11 Région Parisienne  adultes      69 65 ans et +    71.5     173 (65,70]
## 12 Région Parisienne  adultes      29   25-34 ans      60     165 (25,30]
##    age.cat2 poids
## 6   (51,79]  53.0
## 7   (51,79]  66.5
## 9   (32,51]  73.0
## 10  (14,32]  58.0
## 11  (51,79]  71.5
## 12  (14,32]  60.0

Les filtres sur les observations peuvent être multiples et on utilisera le symbole & pour désigner une conjonction (« et » logique) de critères de sélection des lignes du data frame.

selection=subset(indiv,loc_log=="centre ville " & v2_age>60, 
               c(v2_age,loc_log,poids))
head(selection)
##    v2_age       loc_log poids
## 6      61 centre ville   53.0
## 7      76 centre ville   66.5
## 11     69 centre ville   71.5
## 15     61 centre ville   48.3
## 23     66 centre ville   52.0
## 29     67 centre ville   78.0

4.2 Tableau d’effectifs et de fréquences relatives

Le tableau d’effectifs pour la variable age.cat que nous avions construite peut être stocké dans un objet que nous appellerons tab.

tab=table(indiv$age.cat)

À partir du moment où le tableau d’effectifs a été sauvegardé dans un objet,il devient possible d’effectuer un certain nombre d’opération élémentaires comme, par exemple, compter le nombre total d’observations à l’aide de la commande sum(). Les opérations arithmétiques s’effectuant élément par élément sous R, il est même possible d’obtenir les fréquences relatives par simple division des éléments de tab avec le total sum(tab).

sum(tab)
## [1] 4079
tab/sum(tab)
## 
##      (0,5]     (5,10]    (10,15]    (15,20]    (20,25]    (25,30] 
## 0.03996077 0.10075999 0.14341750 0.09928904 0.04682520 0.04756068 
##    (30,35]    (35,40]    (40,45]    (45,50]    (50,55]    (55,60] 
## 0.06153469 0.07452807 0.06864428 0.06128953 0.07183133 0.06374111 
##    (60,65]    (65,70]    (70,75]    (75,80] 
## 0.04265751 0.03407698 0.02770287 0.01618044

Cependant, il existe une commande dont le rôle est précisément de fournir les fréquences relatives, prop.table(), et qui se révélera beaucoup plus utile dans le cas des tableaux à deux entrées.

prop.table(tab)
## 
##      (0,5]     (5,10]    (10,15]    (15,20]    (20,25]    (25,30] 
## 0.03996077 0.10075999 0.14341750 0.09928904 0.04682520 0.04756068 
##    (30,35]    (35,40]    (40,45]    (45,50]    (50,55]    (55,60] 
## 0.06153469 0.07452807 0.06864428 0.06128953 0.07183133 0.06374111 
##    (60,65]    (65,70]    (70,75]    (75,80] 
## 0.04265751 0.03407698 0.02770287 0.01618044

Notons également qu’il est possible de limiter l’affichage des décimales à l’aide de round(), en précisant le nombre de décimales à afficher en deuxième argument. Si au lieu des fréquences relatives on souhaite afficher des pourcentages, on multipliera simplement les fréquences relatives renvoyées par prop.table()par 100.

round(prop.table(tab)*100, 1)
## 
##   (0,5]  (5,10] (10,15] (15,20] (20,25] (25,30] (30,35] (35,40] (40,45] 
##     4.0    10.1    14.3     9.9     4.7     4.8     6.2     7.5     6.9 
## (45,50] (50,55] (55,60] (60,65] (65,70] (70,75] (75,80] 
##     6.1     7.2     6.4     4.3     3.4     2.8     1.6

4.3 Diagramme en barres

La commande barplot() permet de construire des diagrammes en barres (encore appelés diagrammes en bâtons) pour résumer la distribution d’effectifs observée pour une variable catégorielle à k modalités. On fournit à cette commande non pas une variable mais directement un tableau d’effectifs ou de fréquences construit avec table(). Les principaux paramètres graphiques permettant de personnaliser le rendu final de la figure 4 représentant la distribution des classes d’âge sont illustrés dans l’instruction suivante.

Distribution des classes d'âge Distribution des classes d’âge

barplot(prop.table(tab) * 100, 
        ylab="Proportion", col="cornflowerblue",
        border=NA, ylim=c(0, 15), las=1)

4.4 Histogramme

La commande hist() permet de représenter la distribution d’une variable numérique (continue ou discrète) sous forme d’effectif ou de densité. Le nombre de classes, ainsi que la largeur des intervalles de classe, peuvent être paramétrés à l’aide des options nclass= et breaks=. La figure 5 montre une application de cette commande pour la variable poids. Notons qu’une courbe de densité a été ajoutée à l’histogramme. Pour cela, vous utilisez la commande lines() qui permet de travailler sur la même fenêtre graphique et superposer plusieurs éléments graphiques. Le nombre total d’observations peut être ajouté au graphique, à l’aide de paste() qui permet de juxtaposer du texte libre et, par exemple, des expressions R.

hist(indiv$poids, nclass=25, prob=TRUE, col="cornflowerblue", border="white",
xlim=c(10,120), main="", xlab="Poids en Kg", ylab="Densité")
lines(density(indiv$poids, na.rm=TRUE), lwd=2, col="orange")
text(20, 0.015, paste("N =", sum(complete.cases(indiv$poids))), cex=0.8)
Histogramme et densité des poids

Histogramme et densité des poids

4.5 Comparaisons de deux moyennes

Nous pouvons tester la différence des âges entre le groupe des hommes et le groupe des femmes à l’aide d’un test t:

ttres = t.test(v2_age ~sexe_ps , data=indiv)
        print(ttres)
## 
##  Welch Two Sample t-test
## 
## data:  v2_age by sexe_ps
## t = 1.6866, df = 3733.1, p-value = 0.09175
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
##  -0.1802731  2.4000662
## sample estimates:
## mean in group femme  mean in group homme  
##             33.99609             32.88620

Le test t suppose que la variable âge soit distribuée selon une loi Normale et l’égalité des variances intra-groupes. Lorsque ces conditions ne sont pas satisfaites, il convient d’utiliser des tests non-paramètrique.

with(indiv, wilcox.test(v2_age ~ sexe_ps, correct=FALSE))
## 
##  Wilcoxon rank sum test
## 
## data:  v2_age by sexe_ps
## W = 2120000, p-value = 0.0437
## alternative hypothesis: true location shift is not equal to 0
        ksres = with(indiv, ks.test(v2_age[sexe_ps=="femme "], v2_age[sexe_ps=="homme "]))
        
        print(ksres)
## 
##  Two-sample Kolmogorov-Smirnov test
## 
## data:  v2_age[sexe_ps == "femme "] and v2_age[sexe_ps == "homme "]
## D = 0.061203, p-value = 0.001094
## alternative hypothesis: two-sided

Nous pouvons également tracer les fonctions de densité estimées de l’âge pour les deux groupes, et marquer certaines zones du graphique afin d’illuster le chevauchement des deux tracés. Afin d’automatiser cette tâche, vous pouvez créer votre propre fonction7 La fonction ifelse() est utilisée avec trois arguments, la condition, le résultat si la condition est vraie et le résultat si la condition est fausse. (plotdens)

 plotdens = function(x,y, mytitle, mylab)  {
          densx = density(x)
          densy = density(y)
          plot(densx, main=mytitle, lwd=3, xlab=mylab, ylab="Densité", 
               ylim=c(0,max(max(densx$y),max(densy$y))),bty="l",cex.main=0.8)
          lines(densy, lty=1, col=2, lwd=3)  
          xvals = c(densx$x, rev(densy$x))  
          yvals = c(densx$y, rev(densy$y))  
          polygon(xvals, yvals, col="cornflowerblue")
        } 

Une fois exécutée la fonction plotdens peut être appelée comme les autres fonctions de R:

mytitle = paste("Test de Kolmogorov-Smirnov D=", round(ksres$statistic, 3),
                          " p=", round(ksres$p.value, 4), sep="") 
          with(indiv, plotdens(v2_age[sexe_ps=="femme "], v2_age[sexe_ps=="homme "], 
                               mytitle=mytitle, mylab="âge (années)")) 
          legend(60, .02, legend=c("femme", "homme"), col=1:2, lty=1, lwd=2) 
Comparer deux fonctions de densité

Comparer deux fonctions de densité

Considérons maintenant la variable âge et la variable type du lieu d’habitation. Vous pouvez obtenir les résumés des distributions avec summary() pour la variable quantitative et table() pour la variable qualitative.

summary(indiv$v2_age)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    3.00   14.00   32.00   33.51   51.00   79.00
table(indiv$loc_log)
## 
##      bourg ou village           centre ville       habitat dispersé  
##                   1047                   1148                    446 
## quartier périphérique  
##                   1438

nous allons créer une nouvelle variable habitation: avec les modalités 1:“centre ville” et 0: “non centre ville”8 La fonction sort() appliquée à table a permis de trier le tableau des fréquences dans l’ordre croissant des effectifs..

indiv$habitation=ifelse(indiv$loc_log=="centre ville ",1,0)
## vérification
table(indiv$habitation)
## 
##    0    1 
## 2931 1148

Plutôt que d’utiliser des histogrammes pour représenter la distribution des poids selon le lieu d’habitation, il est parfois préférable d’utiliser des courbes de densité, qui peuvent être superposées dans le même graphique.

Courbes de densité de l'âge en fonction du type de lieu d'habitation Courbes de densité de l’âge en fonction du type de lieu d’habitation

plot(density(indiv$v2_age[indiv$habitation == 1], 
    na.rm=TRUE), lwd=2, col="orange", xlim=c(19,83), 
    main="")
lines(density(indiv$v2_age[indiv$habitation == 0],
      na.rm=TRUE), lwd=2,col="deepskyblue4")

Pour calculer la moyenne des âges par type de lieu d’habitation, R propose différentes commandes qui permettent d’appliquer une instruction à des sous-ensembles d’observations définis par une variable qualitative. En plus de la commande by(), il existe tapply() qui nécessite de spécfier les arguments suivants: la vraible numérique (exemple: âge), le facteur permettant de définir les groupes (habitation), et la commande (mean), suivie éventuellement de ses propres options (na.rm=TRUE):

tapply(indiv$v2_age, indiv$habitation, mean, na.rm=TRUE)
##        0        1 
## 33.37871 33.85627

Le calcul de la moyenne par groupe peut être réalisé à l’aide de la fonction aggregate(). Elle fonctionne comme tapply() mais accepte une notation par formule et le résultat renvoyer est un data.frame.

aggregate(v2_age ~ habitation, data=indiv, mean)
##   habitation   v2_age
## 1          0 33.37871
## 2          1 33.85627

La fonction aggregate() peut être utilisée pour calculer d’autre statistique que la moyenne. Par exemple, pour calculer les variance:

aggregate(v2_age ~ habitation, data=indiv, var)
##   habitation   v2_age
## 1          0 436.8893
## 2          1 411.1746

4.6 BoxPlot

Les BoxPlots ou boîte à moustaches peuvent être utilisés pour résumer la distribution des âges selon le lieu d’habitation. Boxplot utilise le même principe de formule que la fonction aggrgate().

Diagrammes boîtes à moustaches Diagrammes boîtes à moustaches

boxplot(v2_age ~ habitation, data=indiv,
xlab="Habitation 1: centre ville, 0: autres", 
ylab="Âge (années)",
col="cornflowerblue", border="cornflowerblue")

Explication du diagramme Boxplot: Un box-plot est un graphique simple composé d’un rectangle duquel deux segments sortent afin de représenter certains éléments des données:
La valeur centrale du graphique est la médiane (il existe autant de valeurs supérieures qu’inférieures à cette valeur dans l’échantillon).
Les bords du rectangle sont les quartiles (Pour le bord inférieur, un quart des observations ont des valeurs plus petites et trois quart ont des valeurs plus grandes, le bord supérieur suit le même raisonnement).

*Les extrémités des moustaches sont calculées en utilisant 1.5 fois l’espace interquartile (la distance entre le 1er et le 3ème quartile).

Explication du diagramme à moustaches

Explication du diagramme à moustaches

4.7 Diagrammes en secteurs

Vous pouvez présenter les données d’une variable qualitative (exemple loc_log) sous la forme d’un diagramme en secteur avec la fonction pie():

Diagrammes en secteurs Diagrammes en secteurs

pie(table(indiv$loc_log),cex=1.3)

Mais c’est une mauvaise idée. En effet, la documentation de la fonction pie() nous dit : Pie charts are a very bad way of displaying information. The eye is good at judging linear measures and bad at judging relative areas. A bar chart or dot chart is a preferable way of displaying this type of data. Il est donc préférable de construire le graphe de Cleveland à l’aide de la fonction dotchart() après avoir trier les données de la table9 En utilisant la syntaxe suivante: fun <- function(arguments) {expression}

dotchart(sort(table(indiv$loc_log)),  pch = 20,col=1:4,cex=0.8)

Graphe de Cleveland

Graphe de Cleveland

4.8 Les nuages de points (scatterplot)

Pour croiser deux variables numériques, vous pouvez utiliser un nuage de points, où chaque point représente un individu. Exemple :

plot(x = indiv$taillem, y = indiv$poids, pch = 20,
xlab = "Taille en cm", ylab = "Poids en kg", las = 1)

Nuage de points

Nuage de points

L’exemple suivant montre comment il est possible de représenter un nuage de points par groupe:

plot(x = indiv$taillem[indiv$sexe_ps=="femme "], y = indiv$poids[indiv$sexe_ps=="femme "],pch=22, 
xlab = "Taille en cm", ylab = "Poids en kg", las = 1,col=1)
points(indiv$taillem[indiv$sexe_ps=="homme "], y = indiv$poids[indiv$sexe_ps=="homme "],col=2,pch=25)
legend(90, 120, legend=c("femme", "homme"), col=1:2,lty=0, lwd=2,pch=c(22,25))

Nuage de points par groupe

Nuage de points par groupe
\newpage

5 Programmer sous R

Sous R, les éléments de base sont des objets : vecteurs, matrices, listes …, sur lesquels sont appliquées des fonctions qui fournissent des résultats numériques et graphiques. Ces objets se différencient par leur mode décrivant leur contenu, et leur classe décrivant leur structure. Les objets atomiques sont de mode homogène et les objets récursifs (listes) sont de mode hétérogène.

Les différents modes sont null (objet vide), logical, numeric, complex, character. Les classes d’objets les plus courantes sont : vector, matrix, array, factor, data.frame, list. On peut avoir des vecteurs, matrices, tableaux, … de mode null (objet vide), logical (TRUE, FALSE, NA), numeric, complex, character tandis que les listes et les data frame peuvent être composés d’éléments hétérogènes. Une confusion entre classes d’objets dans l’appel d’une fonction est la source d’erreur la plus fréquente.

Modes disponibles et contenus correspondants

Mode Contenu
numeric nombre réels
complex nombres complexes
logical valeurs booléennes(vrai/faux)
character chaînes de caractères
function fonction
list données quelconques
expression expression non évaluée

Les fonctions is/as permettent de vérifier ou de contraindre (lorsque c’est possible) le type d’objet. Exemples:

x=3
x
## [1] 3
is.complex(x)
## [1] FALSE
as.complex(x)
## [1] 3+0i
as.character(x)
## [1] "3"
as.integer(T)
## [1] 1
as.integer(F)
## [1] 0

5.1 Conventions pour les noms d’objets

Les caractères permis pour les noms d’objets sont les lettres minuscules a–z et majuscules A–Z, les chiffres 0–9, le point « . » et le caractère de soulignement « _ ». Selon l’environnement linguistique de l’ordinateur, il peut être permis d’utiliser des lettres accentuées, mais cette pratique est fortement déconseillée puisqu’elle risque de nuire à la portabilité du code. voici quelques remarques importantes sur l’attribution des noms aux objets:

5.2 Les vecteurs

Un vecteur regroupe des éléments de même type. La création d’un vecteur peut se faire par la commande c(e1,e2,…). On peut également générer une séquence avec la commande seq(a,b,t) débutant par a inférieure ou égale à b et de pas t ; rep(x,n) est un vecteur répétant n fois l’élément x.

v=c(2,6,7,10,11,27,28,12,9,0)
v
##  [1]  2  6  7 10 11 27 28 12  9  0
is.vector(v)
## [1] TRUE
c(1,2,4,"cinq")
## [1] "1"    "2"    "4"    "cinq"

Séquences et Répétitions

1:10
##  [1]  1  2  3  4  5  6  7  8  9 10
seq(from=1,to=10,by=0.5)
##  [1]  1.0  1.5  2.0  2.5  3.0  3.5  4.0  4.5  5.0  5.5  6.0  6.5  7.0  7.5
## [15]  8.0  8.5  9.0  9.5 10.0
seq(1,40,by=5)
## [1]  1  6 11 16 21 26 31 36
seq(-5,20,length=5)
## [1] -5.00  1.25  7.50 13.75 20.00
rep(5,times=10)
##  [1] 5 5 5 5 5 5 5 5 5 5
rep(c(1,2),3)
## [1] 1 2 1 2 1 2
rep(c(1,2),each=3)
## [1] 1 1 1 2 2 2
e = rep(1,3)
e
## [1] 1 1 1

Extraction dans un vecteur par [ ] et valeurs manquantes

v
##  [1]  2  6  7 10 11 27 28 12  9  0
v[2];v[2:3];v[-3]
## [1] 6
## [1] 6 7
## [1]  2  6 10 11 27 28 12  9  0
# attention aux indices :
v[-(1:2)]
## [1]  7 10 11 27 28 12  9  0
# NA (Not Available) signale une donnée manquante
v[3]=NA;v;summary(v)
##  [1]  2  6 NA 10 11 27 28 12  9  0
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##    0.00    6.00   10.00   11.67   12.00   28.00       1
is.na(v)
##  [1] FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
# fonctions "any" et "all"
any(is.na(v));all(is.na(v))
## [1] TRUE
## [1] FALSE

Labels et opérations

f = c(a=12,b=26,c=32,d=41);f
##  a  b  c  d 
## 12 26 32 41
names(f);f["a"]
## [1] "a" "b" "c" "d"
##  a 
## 12
names(f)=c("a1","a2","a3","a4")
f>30;f[f>30] # noter les différences
##    a1    a2    a3    a4 
## FALSE FALSE  TRUE  TRUE
## a3 a4 
## 32 41
which(f>30)
## a3 a4 
##  3  4
f[2] = 22;f+100
##  a1  a2  a3  a4 
## 112 122 132 141
cos(f);length(f);sum(f)
##         a1         a2         a3         a4 
##  0.8438540 -0.9999608  0.8342234 -0.9873393
## [1] 4
## [1] 107
t(f) # transposition
##      a1 a2 a3 a4
## [1,] 12 22 32 41
e=rep(2,4); 2*e; 2+e
## [1] 4 4 4 4
## [1] 4 4 4 4
e+f ; e*f # opérations terme à terme
## a1 a2 a3 a4 
## 14 24 34 43
## a1 a2 a3 a4 
## 24 44 64 82
f[2] = 22;f+100;f+v # un problème ?
##  a1  a2  a3  a4 
## 112 122 132 141
##  [1] 14 28 NA 51 23 49 60 53 21 22
cos(f);length(f);sum(f)
##         a1         a2         a3         a4 
##  0.8438540 -0.9999608  0.8342234 -0.9873393
## [1] 4
## [1] 107
t(f) # transposition
##      a1 a2 a3 a4
## [1,] 12 22 32 41
e=rep(2,4); 2*e; 2+e
## [1] 4 4 4 4
## [1] 4 4 4 4
e+f ; e*f # opérations terme à terme
## a1 a2 a3 a4 
## 14 24 34 43
## a1 a2 a3 a4 
## 24 44 64 82
t(f)%*%e # produit scalaire
##      [,1]
## [1,]  214
a<-c(3,-1,5,2,-7,3,9)
abs(a);sort(a);order(a)
## [1] 3 1 5 2 7 3 9
## [1] -7 -1  2  3  3  5  9
## [1] 5 2 4 1 6 3 7
a<-c(3,-1,5,2,-7,3,9)
abs(a);sort(a);order(a)
## [1] 3 1 5 2 7 3 9
## [1] -7 -1  2  3  3  5  9
## [1] 5 2 4 1 6 3 7

5.3 Facteurs

Un facteur est un vecteur avec une liste prédéfinie de valeurs, les niveaux (levels). Cela correspond typiquement à une variable qualitative nominale.

vect=c("a","b","c","b","b","a")
vect
## [1] "a" "b" "c" "b" "b" "a"
vect.f=as.factor(vect)
vect.f
## [1] a b c b b a
## Levels: a b c
as.integer(vect.f)
## [1] 1 2 3 2 2 1
as.character(vect.f)
## [1] "a" "b" "c" "b" "b" "a"

5.4 Matrices

Comme les vecteurs, les matrices sont de type quelconque mais ne contiennent que des éléments de même nature. Pour créer une matrice, on utilise la commande matrix(vec,nrow=n,ncol=p) où vec est le vecteur contenant les éléments de la matrice de taille n par p, qui seront rangés en colonne sauf si l’option byrow=T est utilisée.

A = matrix(1:15,ncol=5);A
##      [,1] [,2] [,3] [,4] [,5]
## [1,]    1    4    7   10   13
## [2,]    2    5    8   11   14
## [3,]    3    6    9   12   15
B = matrix(1:15,nc=5,byrow=T)
B2=B;B2[1,1]="xxx";B2
##      [,1]  [,2] [,3] [,4] [,5]
## [1,] "xxx" "2"  "3"  "4"  "5" 
## [2,] "6"   "7"  "8"  "9"  "10"
## [3,] "11"  "12" "13" "14" "15"
cbind(A,B);rbind(A,B) # concaténations
##      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## [1,]    1    4    7   10   13    1    2    3    4     5
## [2,]    2    5    8   11   14    6    7    8    9    10
## [3,]    3    6    9   12   15   11   12   13   14    15
##      [,1] [,2] [,3] [,4] [,5]
## [1,]    1    4    7   10   13
## [2,]    2    5    8   11   14
## [3,]    3    6    9   12   15
## [4,]    1    2    3    4    5
## [5,]    6    7    8    9   10
## [6,]   11   12   13   14   15
A[1,3];A[,2];B[2,] # composants
## [1] 7
## [1] 4 5 6
## [1]  6  7  8  9 10
A[1:3,2:4]
##      [,1] [,2] [,3]
## [1,]    4    7   10
## [2,]    5    8   11
## [3,]    6    9   12
g = seq(0,1,length=20)
C = matrix(g,nrow=4)
dim(C)
## [1] 4 5
C[C[,1]>0.1,]  
##           [,1]      [,2]      [,3]      [,4]      [,5]
## [1,] 0.1052632 0.3157895 0.5263158 0.7368421 0.9473684
## [2,] 0.1578947 0.3684211 0.5789474 0.7894737 1.0000000
# ranunif : tirage aléatoire uniforme
D = matrix(runif(16),ncol=4)
D>0.5
##       [,1]  [,2]  [,3]  [,4]
## [1,]  TRUE FALSE  TRUE FALSE
## [2,]  TRUE  TRUE FALSE FALSE
## [3,] FALSE FALSE FALSE  TRUE
## [4,]  TRUE FALSE  TRUE FALSE
D[D[,1]>0.5,2] 
## [1] 0.478810205 0.942519202 0.008980543
A+B;A*B # opérations terme à terme
##      [,1] [,2] [,3] [,4] [,5]
## [1,]    2    6   10   14   18
## [2,]    8   12   16   20   24
## [3,]   14   18   22   26   30
##      [,1] [,2] [,3] [,4] [,5]
## [1,]    1    8   21   40   65
## [2,]   12   35   64   99  140
## [3,]   33   72  117  168  225
cos(A); cos(A[1:2,1:2])
##            [,1]       [,2]       [,3]         [,4]       [,5]
## [1,]  0.5403023 -0.6536436  0.7539023 -0.839071529  0.9074468
## [2,] -0.4161468  0.2836622 -0.1455000  0.004425698  0.1367372
## [3,] -0.9899925  0.9601703 -0.9111303  0.843853959 -0.7596879
##            [,1]       [,2]
## [1,]  0.5403023 -0.6536436
## [2,] -0.4161468  0.2836622
# inversion
solve(A[1:2,1:2])
##            [,1]       [,2]
## [1,] -1.6666667  1.3333333
## [2,]  0.6666667 -0.3333333
# produit matriciel
t(A) %*% B
##      [,1] [,2] [,3] [,4] [,5]
## [1,]   46   52   58   64   70
## [2,]  100  115  130  145  160
## [3,]  154  178  202  226  250
## [4,]  208  241  274  307  340
## [5,]  262  304  346  388  430
A[1:2,1:2] %*% B[1:2,1:3]
##      [,1] [,2] [,3]
## [1,]   25   30   35
## [2,]   32   39   46
t(B); diag(A)
##      [,1] [,2] [,3]
## [1,]    1    6   11
## [2,]    2    7   12
## [3,]    3    8   13
## [4,]    4    9   14
## [5,]    5   10   15
## [1] 1 5 9
apply(A,2,sum) 
## [1]  6 15 24 33 42
apply(D,1,max)
## [1] 0.7672717 0.9425192 0.7347609 0.7115704
# Eléments propres
s=eigen(A[1:2,2:3])
s$values
## [1] 12.244998 -0.244998
s$vectors
##            [,1]       [,2]
## [1,] -0.6472056 -0.8550584
## [2,] -0.7623155  0.5185316

5.5 Les listes

Une liste est une collection ordonnée d’objets qui peuvent être de classes différentes. Les listes sont en particulier utilisées par certaines fonctions pour renvoyer des résultats complexes sous forme d’un seul objet. On utilise la fonction list(nom1=el1,nom2=el2,…)pour générer une liste. On peut accéder à chaque élément de la liste à l’aide de son index entre double crochets [[…]], ou par son nom précédé du signe $.

x = list("xyz",1:8);x
## [[1]]
## [1] "xyz"
## 
## [[2]]
## [1] 1 2 3 4 5 6 7 8
x[[1]];x[[2]]+10 
## [1] "xyz"
## [1] 11 12 13 14 15 16 17 18
y = list(matrice=D,vecteur=f,texte="xyz",scalaire=8)
names(y);y[[1]]
## [1] "matrice"  "vecteur"  "texte"    "scalaire"
##            [,1]        [,2]      [,3]        [,4]
## [1,] 0.68474178 0.478810205 0.7672717 0.128571704
## [2,] 0.70804500 0.942519202 0.4186286 0.048031351
## [3,] 0.01013511 0.126746896 0.3685384 0.734760914
## [4,] 0.71157042 0.008980543 0.5851269 0.001652146
y$matrice;y$vec
##            [,1]        [,2]      [,3]        [,4]
## [1,] 0.68474178 0.478810205 0.7672717 0.128571704
## [2,] 0.70804500 0.942519202 0.4186286 0.048031351
## [3,] 0.01013511 0.126746896 0.3685384 0.734760914
## [4,] 0.71157042 0.008980543 0.5851269 0.001652146
## a1 a2 a3 a4 
## 12 22 32 41
y[c("texte","scal")] 
## $texte
## [1] "xyz"
## 
## $<NA>
## NULL
y[c("texte","scalaire")]
## $texte
## [1] "xyz"
## 
## $scalaire
## [1] 8
length(y)
## [1] 4
length(y$vecteur)
## [1] 4
cos(y$scalaire)+y[[2]][1]
##      a1 
## 11.8545
summary(y)
##          Length Class  Mode     
## matrice  16     -none- numeric  
## vecteur   4     -none- numeric  
## texte     1     -none- character
## scalaire  1     -none- numeric

5.6 Tableau de données (data.frame)

Un data frame est analogue à une matrice dont les colonnes peuvent être hétérogènes. Un tableau de données est un ensemble de vecteurs rangés colonne par colonne, chaque colonne correspondant à une variable, chaque ligne à un individu. En particulier, lors d’études statistiques, les données à étudier sont souvent représentées par un data frame sous R. Pour créer un tableau de données, on peut regrouper des variables de même longueur à l’aide de la commande data.frame(nom1=var1,nom2=var2,…). On peut aussi transformer une matrice en un tableau de données en utilisant la commande as.data.frame(mat).

taille = runif(12,150,180)
masse = runif(12,50,90)
sexe = rep(c("M","F","F","M"),3)
H = data.frame(taille,masse,sexe)
H;summary(H)
##      taille    masse sexe
## 1  158.0637 81.94786    M
## 2  155.9371 62.42993    F
## 3  160.1714 86.81853    F
## 4  174.1804 75.72348    M
## 5  173.8159 74.59815    M
## 6  171.4722 88.50888    F
## 7  154.0794 78.09507    F
## 8  150.2602 72.16378    M
## 9  170.0977 72.20552    M
## 10 155.3758 50.30676    F
## 11 179.7021 57.83264    F
## 12 155.9763 63.02626    M
##      taille          masse       sexe 
##  Min.   :150.3   Min.   :50.31   F:6  
##  1st Qu.:155.8   1st Qu.:62.88   M:6  
##  Median :159.1   Median :73.40        
##  Mean   :163.3   Mean   :71.97        
##  3rd Qu.:172.1   3rd Qu.:79.06        
##  Max.   :179.7   Max.   :88.51
H[1,];H$taille;H$sexe
##     taille    masse sexe
## 1 158.0637 81.94786    M
##  [1] 158.0637 155.9371 160.1714 174.1804 173.8159 171.4722 154.0794
##  [8] 150.2602 170.0977 155.3758 179.7021 155.9763
##  [1] M F F M M F F M M F F M
## Levels: F M

Opérations sur les dataframes

data1= data.frame(x1=1,x2=1:10,a=letters[1:10])
#Par défaut les lignes sont numérotées 1,2 etc.
data1
##    x1 x2 a
## 1   1  1 a
## 2   1  2 b
## 3   1  3 c
## 4   1  4 d
## 5   1  5 e
## 6   1  6 f
## 7   1  7 g
## 8   1  8 h
## 9   1  9 i
## 10  1 10 j
names(data1)
## [1] "x1" "x2" "a"
names(data1)<-c("c1","c2","c3")
head(data1,3)
##   c1 c2 c3
## 1  1  1  a
## 2  1  2  b
## 3  1  3  c
dim( data1)
## [1] 10  3
row.names(data1)<-letters[1:10]
# le vecteur letters contient les lettres de l'alphabet
head(data1,2)
##   c1 c2 c3
## a  1  1  a
## b  1  2  b

Les opérations entre des dataframes sont des opérations terme à terme comme pour les matrices.

A = data.frame(x=1:3,y=2:4)
B = data.frame(xx=1,yy=1:3)
C= data.frame(x=1:3,y=rep("a",3))
A
##   x y
## 1 1 2
## 2 2 3
## 3 3 4
B
##   xx yy
## 1  1  1
## 2  1  2
## 3  1  3
A+B
##   x y
## 1 2 3
## 2 3 5
## 3 4 7
C
##   x y
## 1 1 a
## 2 2 a
## 3 3 a
#Pour extraire un élément ou un bloc, la syntaxe est la même
A$x
## [1] 1 2 3
A[ ,1]
## [1] 1 2 3
#Pour concaténer des dataframes ayant le même nombre de lignes
data.frame (A,B)
##   x y xx yy
## 1 1 2  1  1
## 2 2 3  1  2
## 3 3 4  1  3

5.7 Opérateurs

L’unité de base dans R est le vecteur. Les opérations sur les vecteurs sont effectuées élément par élément :

c(1, 2, 3) + c(4, 5, 6)
## [1] 5 7 9
1:3 * 4:6
## [1]  4 10 18

Si les vecteurs impliqués dans une expression arithmétique ne sont pas de la même longueur, les plus courts sont recyclés de façon à correspondre au plus long vecteur. Cette règle est particulièrement apparente avec les vecteurs de longueur 1 :

1:10 + 2
##  [1]  3  4  5  6  7  8  9 10 11 12
1:10 + rep(2, 10)
##  [1]  3  4  5  6  7  8  9 10 11 12

Si la longueur du plus long vecteur est un multiple de celle du ou des autres vecteurs, ces derniers sont recyclés un nombre entier de fois :

1:10 + 1:5 + c(2, 4) # vecteurs recyclés 2 et 5 fois
##  [1]  4  8  8 12 12 11 11 15 15 19
1:10 + rep(1:5, 2) + rep(c(2, 4), 5) # équivalent
##  [1]  4  8  8 12 12 11 11 15 15 19

Sinon, le plus court vecteur est recyclé un nombre fractionnaire de fois, mais comme ce résultat est rarement souhaité et provient généralement d’une erreur de programmation, un avertissement est affiché :

1:10 + c(2, 4, 6)
##  [1]  3  6  9  6  9 12  9 12 15 12

Grâce à la propriété d’opération élément par élément de R, il devrait être possible — en fait, il est souhaitable — de résoudre le problème sans avoir recours à des boucles.

Le tableau suivant présente les opérateurs mathématiques et logiques les plus fréquemment employés, en ordre décroissant de priorité des opérations. Le tableau contient également les opérateurs d’assignation et d’extraction pré- sentés au chapitre précédent ; il est utile de connaître leur niveau de priorité dans les expressions R. Les opérateurs de puissance (^) et d’assignation à gauche (<-, <<-) sont évalués de droite à gauche ; tous les autres de gauche à droite. Ainsi, 2^2^3 est 2^8, et non 4^3, alors que 1 - 1 - 1 vaut -1, et non 1.

Principaux opérateurs du langage R, en ordre décroissant de priorité

Opérateurs Fonctions
$ extraction d’une liste
^ puissance
- changement de signe
: génération de suites
%*% %% %/% produit matriciel, modulo, division entière
’*’ / multiplication, division
+ - addition, soustraction
< <= == >= > != plus petit, plus petit ou égal, égal, plus grand ou égal, plus grand, différent de
! négation logique
& && « et » logique
|, || « ou » logique
-> ->> assignation
<- <<- assignation

5.8 Appels de fonctions

Les opérateurs du tableau 2 ne sont que des raccourcis utiles pour accéder aux fonctions les plus courantes de R. Pour toutes les autres, il faut appeler la fonction directement. Nous allons dans cette partie passer en revue les règles d’appels d’une fonction et la façon de spécifier les arguments, qu’il s’agisse d’une fonction interne de R ou d’une fonction personnelle :

Par exemple, la définition de la fonction matrix est la suivante:
matrix(data = NA, nrow = 1, ncol = 1, byrow = FALSE, dimnames = NULL)
matrix() compte cinq argument: data, nrow, ncol, byrow et dimanmes. Ici chaque argument a une valeur par défaut (ce n’est pas toujours le cas). Ainsi, un appel de la fonction matrix()sans argument produira une matrice de dimension 1x1 rempli de l’objet NA et dont les dimensions sont sans étiquette.

5.9 Des fonctions utiles

Le langage R compte un très grand nombre (des milliers !) de fonctions internes. Nous présentons ici les fonctions de base les plus souvent utilisées pour programmer en R et pour manipuler des données.

Manipuler des vecteurs

Manipulation de vecteurs

Nom Fonction Exemple
seq génération de suites de nombres seq(1, 9, by = 2)
seq_len version plus rapide de seq seq_len(10)
rep répétition de valeurs ou de vecteurs rep(2, 10)
sort tri en ordre croissant ou décroissant sort(c(4, -1, 2, 6))
rank rang des éléments (ordre croissant ou décroissant) rank(c(4, -1, 2, 6))
order ordre d’extraction des éléments order(c(4, -1, 2, 6))
rev renverser un vecteur rev(1:10)
head extraction ou suppression des n premiers éléments head(1:10, 3); head(1:10, -3)
tail extraction ou suppression des n derniers éléments tail(1:10, 3); tail(1:10, -3)
unique extraction des éléments différents d’un vecteur unique(c(2, 4, 2, 5, 9, 5, 0))
Les exemples des fonctions suivantes utilisent x x=c(4,-1,2,-3,6)
which positions des valeurs TRUE dans un vecteur booléen which(x < 0)
which.min position du minimum dans un vecteur which.min(x)
which.max position du maximum dans un vecteur which.max(x)
match position de la première occurrence d’un élément match(2, x)
%in% appartenance d’une ou plusieurs valeurs à un vecteur -1:2 %in% x

Arrondi
Il existe plusieurs fonctions d’arrondi:

x=c(-3.6800000,-0.6666667, 3.1415927,0.3333333, 2.5200000)
round(x)#arrondi à un nombre défini de décimales (par défaut 0)
## [1] -4 -1  3  0  3
floor(x)#plus grand entier inférieur ou égal à l’argument
## [1] -4 -1  3  0  2
ceiling(x)#plus petit entier supérieur ou égal à l’argument
## [1] -3  0  4  1  3
trunc(x)#troncature vers zéro ; différent de floor pour les nombres négatifs
## [1] -3  0  3  0  2

Résumés statistiques
Le tableau suivant présente quelques fonctions pour les statistiques descriptives:

Résumés statistiques

Nom Fonction Exemple
sum, prod somme et produit des éléments d’un vecteur sum(x); prod(x)
diff différences entre les éléments d’un vecteur diff(x)
mean moyenne arithmétique (tronquée avec l’argument trim) mean(x)
var, sd variance et écart type var(x), sd(x)
min, max minimum et maximum d’un vecteur min(x); max(x)
range vecteur contenant le min et le max d’un vecteur range(x)
median médiane empirique median(x)
quantile quantiles empiriques quantile(x)
summary statistiques descriptives d’un échantillon summary(x)

5.10 Les lois de Probabilités

R dispose d’un package de base dédié aux statitistique (stats), qui est chargé par défaut. Il permet entre autre d’utiliser les lois statistiques telles que les lois bêta, binomiale, de Cauchy, \(\chi^2\), exponentielle, F de Fisher, gamma, géométrique, hypergéométrique, lognormale, multinomiale, binomiale négative, normale, de Poisson, t de Student, uniforme, de Weibull, etc. Pour chacune de ces lois, R fournit, lorsqu’elle est définie, la densité de probabilité, la fonction de répartition (probabilités cumulées), la fonction de probabilité inverse (quantiles) et un générateur de nombres aléatoires suivant cette loi. Les noms des fonctions sont déterminés de manière systématique.

Loi Normale

Loi Normale Loi Normale

Les arguments des fonctions dépendent des paramètres des lois.
Une loi normale admet deux paramètres : l’espérance (ou moyenne, mean) \(\mu\) (mu) et l’écart type (standard deviation) \(\sigma\) (sigma). Les fonctions associées à la loi normale sont donc les suivantes :

Nom des fonctions liées aux lois de probabilité

Loi..suffixe Densité.de.probabilité Fonction.de.répartition Quantiles Générateur.aléatoire
d p q r
bêta, beta dbeta pbeta qbeta rbeta
binomiale, binom dbinom pbinom qbinom rbinom
de Cauchy, cauchy dcauchy pcauchy qcauchy rcauchy
Chi2, chisq dchisq pchisq qchisq rchisq
exponentielle, exp dexp pexp qexp rexp
F, f df pf qf rf
gamma, gamma dgamma pgamma qgamma rgamma
géométrique, geom dgeom pgeom qgeom rgeom
hypergéométrique, hyper dhyper phyper qhyper rhyper
log-normale, lnorm dlnorm plnorm qlnorm rlnorm
multinomiale, multinorm dmultinorm pmultinorm qmultinorm rmultinorm
binomiale négative, nbinom dnbinom pnbinom qnbinom rnbinom
normale, norm dnorm pnorm qnorm rnorm
de Poisson, pois dpois ppois qpois rpois
t de Student, t dt pt qt rt
uniforme, unif dunif punif qunif runif
de Weibull, weibull dweibull pweibull qweibull rweibull

Loi Uniforme
Une loi uniforme admet deux paramètres : le minimum a et le maximum b de l’intervalle de définition. Nous avons donc :
- dunif(x) : densité de probabilité en x de la uniforme sur [0 ; 1] ;
- dunif(x, a, b) ou dunif(x, min = a, max = b) : densité de probabilité en x de la loi uniforme sur [a ; b]

Loi Binomiale
Une loi binomiale admet deux paramètres : la taille de l’échantillon (size, nombre de tirages) n et la probabilité de réussite de chaque épreuve, P. Nous avons donc :
- dbinom(k, n, P) ou dbinom(k, size = n, prob = P) : probabilité d’avoir k réussites parmi n tirages

Loi Exponentielle
Une loi exponentielle admet un paramètre : le taux (rate) \(\lambda\) (lambda). Nous avons donc :
- dpois(k, l) ou dpois(k, lambda = l) : densité de probabilité en k de la loi de Poisson de paramètre l

5.11 Fonctions personnelles

L’une des grandes forces de R est la possibilité pour l’utilisateur de définir facilement et rapidement de nouvelles fonctions. Les fonctions personnelles définies dans l’espace de travail ou dans un package sont traitées par le système exactement comme les fonctions internes. Vous devriez envisager d’écrire une fonction chaque fois que vous avez copié et collé un bloc de code plus de deux fois (c’est-à-dire que vous avez maintenant trois copies du même code). Par exemple, examinez le code suivant :

df  = data.frame(
  a = rnorm(10),
  b = rnorm(10),
  c = rnorm(10),
  d = rnorm(10)
)

df$a <- (df$a - min(df$a, na.rm = TRUE)) / 
  (max(df$a, na.rm = TRUE) - min(df$a, na.rm = TRUE))
df$b <- (df$b - min(df$b, na.rm = TRUE)) / 
  (max(df$b, na.rm = TRUE) - min(df$a, na.rm = TRUE))
df$c <- (df$c - min(df$c, na.rm = TRUE)) / 
  (max(df$c, na.rm = TRUE) - min(df$c, na.rm = TRUE))
df$d <- (df$d - min(df$d, na.rm = TRUE)) / 
  (max(df$d, na.rm = TRUE) - min(df$d, na.rm = TRUE))

A ce stade, vous devriez être capable de déchifrer ce code et comprendre que je cherche à redimensionner les variables entre 0 et 1. Mais avez-vous repéré l’erreur? J’ai fait une erreur en copiant-et-collant le code pour df$b: J’ai oublié de changer un a en un b. Extraire le code répété dans une fonction est une bonne idée car il vous empêche de faire ce type d’erreur. Pour écrire une fonction, vous devez d’abord analyser le code. Combien y a-t-il d’entrées?

(df$a - min(df$a, na.rm = TRUE)) /
  (max(df$a, na.rm = TRUE) - min(df$a, na.rm = TRUE))

Ce code n’a qu’une seule entrée: df$a. Pour rendre les entrées plus claires, il convient de réécrire le code en utilisant des variables temporaires avec des noms généraux. Ici, ce code ne nécessite qu’un seul vecteur numérique, donc je vais appeler x:

x <- df$a
(x - min(x, na.rm = TRUE)) / (max(x, na.rm = TRUE) - min(x, na.rm = TRUE))
#>  [1] 0.289 0.751 0.000 0.678 0.853 1.000 0.172 0.611 0.612 0.601

Le code refait un même calcul plusieurs fois. Nous calculons l’étendue (max-min) des données trois fois, mais il est logique de le faire en une seule étape:

rng <- range(x, na.rm = TRUE)
(x - rng[1]) / (rng[2] - rng[1])
#>  [1] 0.289 0.751 0.000 0.678 0.853 1.000 0.172 0.611 0.612 0.601

Maintenant que nous avons simplifié le code et vérifié qu’il fonctionne correctement, nous pouvons le transformer en une fonction :

rescale01 <- function(x) {
  rng <- range(x, na.rm = TRUE)
  (x - rng[1]) / (rng[2] - rng[1])
}
rescale01(c(0, 5, 10))
## [1] 0.0 0.5 1.0

Trois étapes clés pour créer une nouvelle fonction10 Un sondage aléatoire simpe consiste à dresser une liste exhaustive de toutes les unités de la population étudiée (base de sondage) et à procéder à un tirage au sort à l’aide par exemple d’une table de nombres au hasard. Avec cette procédure, toutes les unités de sondage ont la même probabilité d’appartenir à l’échantillon.:

  1. Choisissez un nom pour la fonction (dans l’exemple nous avons utilisé rescale01 parce que cette fonction change l’échelle des valeurs entre 0 et 1.

  2. Déclarez les entrées, ou les arguments, de la fonction à l’intérieur de la fonction (dans l’exemple nous avons un seul argument. Si nous avions plusieurs l’appel ressemblerait à la fonction (x, y, z)).

  3. Placez le code que vous avez développé dans le corps de la fonction, un bloc {…} qui suit immédiatement la fonction (…).

Notez bien l’ensemble du processus : Nous avons créer la fonction seulement après que nous ayons compris son fonctionnement avec une entrée simple. De plus, Il est important de vérifier le fonctionnement d’un code avant de le transformer en une fonction. À ce stade, il convient de vérifier votre fonction avec quelques entrées différentes:

rescale01(c(-10, 0, 10))
## [1] 0.0 0.5 1.0
rescale01(c(1, 2, 3, NA, 5))
## [1] 0.00 0.25 0.50   NA 1.00

Nous pouvons maintennat simplifier le code de l’exemple original à l’aide de la fonction:

df$a <- rescale01(df$a)
df$b <- rescale01(df$b)
df$c <- rescale01(df$c)
df$d <- rescale01(df$d)

Un autre avantage des fonctions est que si nos besoins changent, nous avons à faire le changement en un seul endroit. Par exemple, nous pouvons découvrir que certaines de nos variables incluent des valeurs infinies, et donc rescale01 () échoue:

x <- c(1:10, Inf)
rescale01(x)
##  [1]   0   0   0   0   0   0   0   0   0   0 NaN

Parce que nous avons extrait le code dans une fonction, nous avons seulement besoin de faire le correctif en un seul endroit:

rescale01 <- function(x) {
  rng <- range(x, na.rm = TRUE, finite = TRUE)
  (x - rng[1]) / (rng[2] - rng[1])
}
rescale01(x)
##  [1] 0.0000000 0.1111111 0.2222222 0.3333333 0.4444444 0.5555556 0.6666667
##  [8] 0.7777778 0.8888889 1.0000000       Inf

Il s’agit d’une partie importante du principe «Ne vous répétez pas» (ou DRY). Plus vous répétez des morceaux de code dans des endroits différents plus la mise à jour de votre code sera compliquée et donc de créer des bugs.

5.12 Exemple de construction d’une fonction

Estimation d’une proportion (prévalence)

Nous considérons la situation où la prévalence est estimée sur la base d’un sondage aléatoire simple11 if (condition) { # code à exécuter si condition est vraie } else { # code à exécuter si condition est fausse }. Sur l’échantillon de taille n on observe k individus avec le signal étudié (Maladie par exemple). La prévalence est estimé par \(p_{0}=\frac{k}{n}\).
Plutôt que de se contenter de cette estimation \(p_{0}\) de la véritable valeur cherchée \(p\) , on préfère calculer un intervalle dans lequel la vraie valeur p a de grandes chances de se trouver : \[p_{0}\pm\varepsilon_{\alpha}\sqrt{\frac{p_{0} (1-p_{0})}{n}}\]

ic_prev=function(k,n,alpha){
        p=k/n
        delta=qnorm(1-alpha/2)*sqrt(p*(1-p)/n)
        c(p-delta,p+delta)
        }
ic_prev(23,100,0.05)
## [1] 0.1475183 0.3124817

Les conditions d’application de cette formule sont: n et n-k soient tous les deux \(\geq\) 5. Nous allons introduire ces conditions dans la fonction. L’exécution du code de calcul de l’intervalle de confiance sera conditionnelle12 Précision absolue :\[\Delta=\varepsilon_{\alpha}\sqrt{\frac{p(1-p)}{n}}\] \[\varepsilon_{\alpha}=qnorm(1-alpha/2)\].

ic_prev=function(k,n,alpha){
  if(k<5|n-k<5) {
              c("n et n-k doivent être >= 5 ")
              }
        else {
        p=k/n
        delta=qnorm(1-alpha/2)*sqrt(p*(1-p)/n)
        c(p-delta,p+delta)
        }
        }
ic_prev(3,100,0.05);ic_prev(96,100,0.05)
## [1] "n et n-k doivent être >= 5 "
## [1] "n et n-k doivent être >= 5 "
ic_prev(30,100,0.05)
## [1] 0.2101832 0.3898168

Calcul de la taille de l’échantillon pour l’estimation d’une prévalence

Le calcul de la taille de l’échantillon nécessite de renseigner le niveau de la prévalence que l’on cherche à estimer et la précision souhaitée13 http://r4ds.had.co.nz/tibbles.html#tibbles-vs.data.frame. A partir de la formule de la précision absolue, il est facile de déduire n en fonction de \(\Delta\), \(p\) et \(\varepsilon_{\alpha}\). \[n=\varepsilon^{2}_{\alpha}\frac{p(1-p)}{\Delta^{2}}\] Cette formule s’applique uniquement lorsque \(\frac{n}{N}\leq 0.10\). Dans le cas contraire un ajustement de la taille de l’échantillon n en fonction N taille de la population est à faire :

\[n^\prime=\frac{1}{\frac{1}{n}+\frac{1}{N}}\]

samplesize_prev=function(p,delta,alpha,N=Inf){
  #N=Inf permet d'avoir une entrée par défaut
  n=(qnorm(1-alpha/2)^2)*p*(1-p)/(delta^2)
  ceiling(ifelse(N==Inf,n,(1/n+1/N)^-1))
  #l'opérateur == est un opérateur logique
  #différent de = qui assigne une valeur à un objet
}
samplesize_prev(.4,0.1,0.05)
## [1] 93
samplesize_prev(.4,0.1,0.05,500)
## [1] 78

6 Les Tibbles

Il ne s’agit pas de faute d’orthographe, tibbles au lieu de tables, mais d’une nouvelle classe d’objet dans R. Un (e) tiblle se comporte exactement comme un(e) data.frame mais leurs options d’impression par défaut sont différenetes14 European Center for Disease Prevention and Control, http://http://ecdc.europa.eu/en/Pages/home.aspx. A partir de cette partie du document, nous allons utilisé un groupe de packages appelé tidyverse. Ce groupe comprend les packages : ggplot2, tibble, tidyr, readr, purrr et dplyr. Si vous exécutez le code library(tidyverse) et obtenez le message d’erreur “il n’y a pas de paquet appelé ‘tidyverse’”, vous devez d’abord l’installer, puis réexécuter la library(tidyverse).

install.packages("tidyverse")
library(tidyverse)

Même si un package est installé dans votre système R, vous devez le recharger à chaque démarrage d’une nouvelle session. Afin de rendre plus explicite la provenance d’une fonction ou d’un objet en général, nous avons la possibilité d’utiliser la forme spéciale suivante : package::function(). Par exemple:

ggplot2::ggplot()
#la fonction ggplot est une fonction du package ggplot2

Pour gérer nos données, nous allons utiliser une grammaire qui repose sur quelques verbes simples:
- select() permet de sélectionner les colonnes d’un jeu de données ;
- filter() permet de filter les lignes en fonction de conditions logiques (par exemple sélectionner les lignes où telle variable est supérieure à telle valeur, etc) ;
- rename() permet de renommer les variables ;
- summarise() permet de résumer ou synthétiser un jeu de données ;
- mutate() permet de définir de nouvelles variables ;
- arrange() permet de trier le tableau de données.

Ces fonctions font partie du package dplyr. Ce dernier contient aussi la fonction group_by qui permet d’exécuter des opérations par sous-groupes du jeu de données.

Le package tidyr vous facilite la mise ne forme de vos données grâce à ses deux principales fonctions:
- gather() pour passer en mode clé-valeur
- spread() pour passer en mode large

6.1 Création d’un tibble à partir d’un fichier csv

Nous prenons comme exemple les données des cas de listériose déclarés en Europe entre 2008 et 201515 N.B. Vous devez écrire nouveau nom = ancien nom. Ce fichier est au format CSV. Pour l’importer, on utilise la fonction read_csv() de la librairie readr.

library(tidyverse)
## Loading tidyverse: ggplot2
## Loading tidyverse: tibble
## Loading tidyverse: tidyr
## Loading tidyverse: readr
## Loading tidyverse: purrr
## Loading tidyverse: dplyr
## Conflicts with tidy packages ----------------------------------------------
## filter(): dplyr, stats
## lag():    dplyr, stats
tbl_list=read_csv("LIST_2008-2015_EU.csv")
## Parsed with column specification:
## cols(
##   `Age Group` = col_character(),
##   Gender = col_character(),
##   Country = col_character(),
##   Month = col_integer(),
##   Year = col_integer(),
##   `Number Of Cases` = col_integer()
## )
tbl_list
## # A tibble: 6,974 × 6
##    `Age Group` Gender Country Month  Year `Number Of Cases`
##          <chr>  <chr>   <chr> <int> <int>             <int>
## 1           00      F Austria     2  2008                 1
## 2           00      F Austria     8  2008                 1
## 3           00      F Austria    11  2008                 1
## 4        19-44      M Austria     7  2008                 1
## 5        19-44      F Austria     6  2008                 1
## 6        19-44      F Austria     7  2008                 1
## 7        45-64      M Austria     5  2008                 1
## 8        45-64      M Austria     8  2008                 2
## 9        45-64      M Austria     9  2008                 1
## 10       45-64      M Austria    10  2008                 1
## # ... with 6,964 more rows

Pour afficher un apperçu différent du tableau, vous pouvez utiliser la fonction glimpse(). Pour enchaîner des instructions nous allons utilser un pipe16 Grâce à la fonction kable()du package knitr comme si les données étaient passées dans un tuyau. Les pipes sont représentées par le code %>%.

tbl_list %>%
  glimpse()
## Observations: 6,974
## Variables: 6
## $ Age Group       <chr> "00", "00", "00", "19-44", "19-44", "19-44", "...
## $ Gender          <chr> "F", "F", "F", "M", "F", "F", "M", "M", "M", "...
## $ Country         <chr> "Austria", "Austria", "Austria", "Austria", "A...
## $ Month           <int> 2, 8, 11, 7, 6, 7, 5, 8, 9, 10, 9, 2, 3, 9, 3,...
## $ Year            <int> 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008...
## $ Number Of Cases <int> 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 2, 2, 1, 1...

Pour un apperçu complet du tableau, utilisez la fonction View()

tbl_list %>%
  View()

Vous avez sans doute remarqué que dans un tibble les noms des colonnes ne sont ni tronqués ni modifiés. Cependant, lorsqu’un nom comporte des espaces ou est un nombre il est mis entre deux guillemets: ` `

6.2 Filter les lignes et sélectionner des colonnes d’un tibble

La fonction filter() permet de filtrer la table en fonction d’une condition logique.

Par exemple, sur la table tbl_list, nous pouvons filtrer la table pour ne garder que les cas de listérioses survenus en France :

tbl_list %>%
  filter(Country=="France")
## # A tibble: 755 × 6
##    `Age Group` Gender Country Month  Year `Number Of Cases`
##          <chr>  <chr>   <chr> <int> <int>             <int>
## 1           00   <NA>  France    11  2008                 1
## 2           00      M  France     1  2008                 2
## 3           00      M  France     9  2008                 1
## 4           00      M  France    12  2008                 1
## 5           00      F  France     3  2008                 1
## 6           00      F  France     5  2008                 2
## 7           00      F  France     9  2008                 1
## 8           00      F  France    11  2008                 2
## 9        01-03      M  France    10  2008                 1
## 10       04-10      M  France     8  2008                 1
## # ... with 745 more rows

Nous pouvons également combiner plusieurs conditions. Dans l’exemple suivant, nous filtrons les cas survenus en France après 2011.

tbl_list %>%
  filter(Country=="France",Year>2011)
## # A tibble: 364 × 6
##    `Age Group` Gender Country Month  Year `Number Of Cases`
##          <chr>  <chr>   <chr> <int> <int>             <int>
## 1        11-18      F  France     5  2012                 1
## 2        11-18      F  France     8  2012                 2
## 3        11-18      F  France    12  2012                 1
## 4        19-44      M  France     1  2012                 1
## 5        19-44      M  France     3  2012                 1
## 6        19-44      M  France     4  2012                 1
## 7        19-44      M  France     5  2012                 1
## 8        19-44      M  France     6  2012                 1
## 9        19-44      M  France     7  2012                 2
## 10       19-44      M  France     8  2012                 1
## # ... with 354 more rows
# "," remplace le symbol &
tbl_list %>%
  filter(Country=="France" & Year>2011)
## # A tibble: 364 × 6
##    `Age Group` Gender Country Month  Year `Number Of Cases`
##          <chr>  <chr>   <chr> <int> <int>             <int>
## 1        11-18      F  France     5  2012                 1
## 2        11-18      F  France     8  2012                 2
## 3        11-18      F  France    12  2012                 1
## 4        19-44      M  France     1  2012                 1
## 5        19-44      M  France     3  2012                 1
## 6        19-44      M  France     4  2012                 1
## 7        19-44      M  France     5  2012                 1
## 8        19-44      M  France     6  2012                 1
## 9        19-44      M  France     7  2012                 2
## 10       19-44      M  France     8  2012                 1
## # ... with 354 more rows
#les deux codes donnent le même résultat

Pour combiner des conditions avec la logique “ou”, vous pouvez utilser le symbol “|”.

La fonction select() est un verbe, qui comme son nom l’indique, permet de sélectionner des variables :

tbl_list %>%
  select(`Number Of Cases`,Country,Year)%>%
  filter(`Number Of Cases`>20)
## # A tibble: 4 × 3
##   `Number Of Cases` Country  Year
##               <int>   <chr> <int>
## 1                21 Germany  2014
## 2                23 Germany  2014
## 3                28 Germany  2015
## 4                21 Germany  2015
  # '' permet d'appeler des variables avec des caractères spéciaux

Il est possible de sélectionner plusieurs colonnes contiguës grâce à l’instruction “X:Z” et de na pas afficher certaines variables en les précédent par le signe “-”. ##Trier les données Une autre opération utile consiste à trier le jeu de données, dans l’ordre croissant ou décroissant selon un ou plusieurs critères. Cette opération s’exécute merveilleusement avec la fonction arrage():

tbl_list %>%
  arrange(Gender)
## # A tibble: 6,974 × 6
##    `Age Group` Gender Country Month  Year `Number Of Cases`
##          <chr>  <chr>   <chr> <int> <int>             <int>
## 1           00      F Austria     2  2008                 1
## 2           00      F Austria     8  2008                 1
## 3           00      F Austria    11  2008                 1
## 4        19-44      F Austria     6  2008                 1
## 5        19-44      F Austria     7  2008                 1
## 6        45-64      F Austria     9  2008                 2
## 7        65-74      F Austria     3  2008                 1
## 8        65-74      F Austria     5  2008                 1
## 9        65-74      F Austria     7  2008                 2
## 10       65-74      F Austria     9  2008                 1
## # ... with 6,964 more rows
# par défaut arrange tri dans l'ordre croissant
tbl_list %>%
  arrange(desc(`Number Of Cases`))%>%
#desc(variable) pour un tris décroissant
#(comme decreasing=True de la fonction sort())
  select(Country,`Number Of Cases`,Year)
## # A tibble: 6,974 × 3
##    Country `Number Of Cases`  Year
##      <chr>             <int> <int>
## 1  Germany                28  2015
## 2  Germany                23  2014
## 3  Germany                21  2014
## 4  Germany                21  2015
## 5  Germany                19  2015
## 6  Germany                18  2013
## 7  Germany                18  2014
## 8  Germany                18  2015
## 9   France                17  2013
## 10 Germany                17  2014
## # ... with 6,964 more rows

Rien n’empêche de multiplier les critères de tri, il suffit de les séparer par des virgules, comme pour select() ou filter().

6.3 La fonction summarise()

Summarise() est une fonction dite de “résumé” qui retourne une seule information. Par exemple la moyenne, la variance, l’effectif….

tbl_list %>%
  summarise(`Nombre total des cas`=sum(`Number Of Cases`))
## # A tibble: 1 × 1
##   `Nombre total des cas`
##                    <int>
## 1                  14929

Le résumé peut être fait par groupe grâce à la fonction group_by(). Le principe consiste à découper le jeu de données puis réaliser des opérations sur chacun des sous-groupes et ensuite combiner les différenst résultats: split -apply - combine.

Traitements par groupe dans un pipe. Source: THINKR

Traitements par groupe dans un pipe. Source: THINKR

tbl_list %>%
  group_by(Country)%>%
  summarise(`Nombre total des cas`=sum(`Number Of Cases`))
## # A tibble: 29 × 2
##           Country `Nombre total des cas`
##             <chr>                  <int>
## 1         Austria                    296
## 2         Belgium                    465
## 3         Croatia                      7
## 4          Cyprus                      5
## 5  Czech Republic                    272
## 6         Denmark                    496
## 7         Estonia                     36
## 8         Finland                    423
## 9          France                   2699
## 10        Germany                   3597
## # ... with 19 more rows

6.4 Renommer les variables et définir de nouvelles variables

La fonction names() permet d’afficher les noms des variables.

tbl_list %>%names()
## [1] "Age Group"       "Gender"          "Country"         "Month"          
## [5] "Year"            "Number Of Cases"

La fonction rename() permet de renommer certaines variable d’un tableau de données. Par exemple vous pouvez renommer la variable Month en mois et Year en année17 La fonction tribble scanne les données d’un tableau où les noms des variables sont précédés par le symbole ~ et séparés par des virgules et les données sont saisies directement avec des séparateurs “,”

tbl_list %>%
  rename(mois=Month, `année`=Year)%>%
  names()
## [1] "Age Group"       "Gender"          "Country"         "mois"           
## [5] "année"           "Number Of Cases"

La fonction mutate() permet de définir de nouvelles variables. Par exemple, sur le data.frame indiv, nous avons le poids et la taille des individus. Nous pouvant calculer l’indice corporel à partir de ses deux variables : \[IC = \frac{poids}{taille^{2}}\] Avec le poids en Kg et la taille en mètre. Pour commencer, nous allons transformer le tableau indiv en tibble.

tbl_indiv=as_data_frame(indiv)%>%
   select(nomen,cod_com,sexe_ps,region,v2_age,taillem,poids)%>%
   rename(ID_indiv=nomen,`code postal`=cod_com,sexe=sexe_ps,age=v2_age,taille=taillem)
tbl_indiv
## # A tibble: 4,079 × 7
##    ID_indiv `code postal`   sexe             region   age taille poids
##       <int>         <int> <fctr>             <fctr> <int>  <int> <dbl>
## 1    110006         77239 femme  Région Parisienne     54    162  82.0
## 2    110007         77239 homme  Région Parisienne     70    170  70.0
## 3    110020         78291 femme  Région Parisienne     43    170  96.0
## 4    110021         78003 femme  Région Parisienne     75    152  53.0
## 5    110025         78003 femme  Région Parisienne     39    165  57.0
## 6    110034         91200 femme  Région Parisienne     61    152  53.0
## 7    110046         91200 homme  Région Parisienne     76    163  66.5
## 8    110057         77143 homme  Région Parisienne     52    175  82.0
## 9    110067         75102 homme  Région Parisienne     38    181  73.0
## 10   110071         75102 femme  Région Parisienne     32    173  58.0
## # ... with 4,069 more rows

Pour créer la nouvelle variable, IC, nous allons utiliser la fonction mutate():

tbl_indiv%>%
  mutate(IC=poids/(taille/100)^2)%>%
  mutate(IC=round(IC,1))%>%
  select(taille,poids,IC)
## # A tibble: 4,079 × 3
##    taille poids    IC
##     <int> <dbl> <dbl>
## 1     162  82.0  31.2
## 2     170  70.0  24.2
## 3     170  96.0  33.2
## 4     152  53.0  22.9
## 5     165  57.0  20.9
## 6     152  53.0  22.9
## 7     163  66.5  25.0
## 8     175  82.0  26.8
## 9     181  73.0  22.3
## 10    173  58.0  19.4
## # ... with 4,069 more rows

Créons un nouveau tbl avec IC et résumons les données:

tbl_indiv2=tbl_indiv%>%
  mutate(IC=poids/(taille/100)^2)%>%
  mutate(IC=round(IC,1))

tbl_indiv2%>%
  summarise(
    `age moyen`=mean(age,na.rm=TRUE),
    `poids moyen`=mean(poids,na.rm=TRUE),
    `taille moyenne`=mean(taille/100,na.rm=TRUE)
  )
## # A tibble: 1 × 3
##   `age moyen` `poids moyen` `taille moyenne`
##         <dbl>         <dbl>            <dbl>
## 1    33.51312      59.78795         1.598846

Avec la flexibilité sur les noms des variables il devient facile de construire des tableaux directement à partir de R18 The Grammar of Graphics (Statistics and Computing) Springer-Verlag New York, Inc. Secaucus, NJ, USA ©2005 ISBN:0387245448.

Tableau résumant des données de tbl_indiv

age moyen poids moyen taille moyenne
33.51312 59.78795 1.598846

Traitons maintenant un jeu de données sur la contamination de certains aliments par l’acrylamide. Ce jeu de données est stocké dans le fichier “acrylamide.csv”. Vous allez importer ces données avec la fonction read.csv puis les transformer en tibble grâce à as_data_frame().

tbl_acrylamide=as_data_frame(read.csv("acrylamide.csv"))
tbl_acrylamide%>%
  names()
## [1] "codal"      "lib"        "année"      "région"     "Unité"     
## [6] "acrylamide"

Le tableau tb_acrylamide a six colonnes: codal, lib, année, région, Unité et acrylamide. Respectivement, il s’agit du code aliment, son libellé, la région où l’échantillon a été pris, l’unité de la mesure et le résultat de recherche de l’acrylamide dans l’échantillon. Chaque ligne correspond à un échantillon. Nous cherchons à calculer la moyenne des concentrations à partir des données du tibble acrylamide:

tbl_acrylamide
## # A tibble: 192 × 6
##     codal           lib année région  Unité acrylamide
##    <fctr>        <fctr> <int>  <int> <fctr>     <fctr>
## 1   92055      sandwich  2007      1  µg/kg       34.2
## 2   92055      sandwich  2008      1  µg/kg         NQ
## 3   92055      sandwich  2008      6  µg/kg         ND
## 4   92055      sandwich  2009      6  µg/kg         NQ
## 5   92055      sandwich  2007      7  µg/kg       20.9
## 6   92055      sandwich  2008      9  µg/kg         36
## 7   92055      sandwich  2008      9  µg/kg         NQ
## 8   92055      sandwich  2007     34  µg/kg         NQ
## 9   92055      sandwich  2008     34  µg/kg         ND
## 10  39230 crème dessert  2007     99  µg/kg         ND
## # ... with 182 more rows

Nous constatons que la variable acrylamide est comprise comme facteur. Ceci est du au fait que dans cette colonne certaines concentrations sont codées par NQ ou ND (Non quantifaible ou non détectable). Pour rendre ces données utilisables, nous devons réaliser différentes opération. Nous allons en premier créer une fonction qui attribuera des valeurs à NQ et à ND :

censure=function(x,LOD,LOQ){
  y=x
  y[y=="NQ"]<-LOQ
  y[y=="ND"]<-LOD
  y
}

Testez votre nouvelle fonction avec un petit jeu de données.
Maintenant nous allons effectuer différentes opérations connectées par des pipes (%>%) :
- créer une nouvelle variable ci à partir de la variable acrylamide
- formater ci en charactère - appliquer la fonction censure sur ci - transformer ci en une variable continue (double)
- grouper les données par région et codal
- calculer la moyenne pour les différents sous groupes formés par le croisement de codal et région

tbl_ci=tbl_acrylamide%>%
  mutate(ci=parse_character(acrylamide))%>%
  #créer une nouvelle variable ci à partir de
  #acrylamide mais avec un format character et non factor 
  mutate(ci=censure(ci,LOD=4,LOQ=10) )%>%
  #on applique la fonction censure qui remplace ND et NQ
  #par LOD et LOQ respectivement
  mutate(ci=parse_double(ci))%>%
  #transforme ci en format double
  group_by(`région`,codal)%>%
  summarise(`moyenne ci`=mean(10*ci,na.rm=TRUE),n=sum(table(codal)))

Tableau des moyennes des ci en (mg/Kg) par région et par aliment

région codal moyenne ci n
1 18002 211.50 2
1 18004 358.00 2
1 18073 264.50 2
1 25019 100.00 2
1 26030 132.50 2
1 4005 6249.00 2
1 404 6922.00 2
1 92055 221.00 2
2 18002 188.50 2
2 18073 256.00 2
2 25019 113.00 2
2 26030 100.00 2
2 4005 6504.50 2
2 404 7013.00 2
5 18073 217.50 2
5 25009 119.50 2
5 26030 101.50 2
5 4005 9918.50 2
5 404 8961.00 2
6 18002 236.50 2
6 18073 1333.00 2
6 25413 132.00 2
6 26030 142.00 2
6 4005 5000.00 2
6 404 11349.00 2
6 92055 70.00 2
7 18002 225.00 2
7 18004 404.00 1
7 18073 942.00 2
7 26030 204.00 2
7 36004 100.00 2
7 36306 281.00 2
7 4005 5935.00 2
7 404 11555.00 2
7 92055 209.00 1
8 18002 232.50 2
8 18073 1245.00 2
8 25019 157.00 2
8 26030 100.00 2
8 4005 8606.00 2
8 404 9818.00 2
9 18002 178.50 2
9 18073 1239.50 2
9 25009 119.50 2
9 25413 70.00 2
9 26030 117.00 2
9 36306 40.00 2
9 4005 12969.00 2
9 404 11376.00 2
9 92055 230.00 2
34 18002 251.00 2
34 18073 290.00 1
34 25089 338.50 2
34 25413 78.00 2
34 26030 188.50 2
34 4005 2745.50 2
34 404 9363.00 2
34 92055 70.00 2
99 13038 40.00 2
99 13108 40.00 2
99 20905 70.00 2
99 20909 40.00 2
99 20911 40.00 2
99 23000 304.00 2
99 23455 179.00 2
99 23499 304.00 2
99 23585 481.50 2
99 23800 232.00 2
99 23909 203.00 2
99 23939 158.00 3
99 24000 1929.50 2
99 24036 2127.50 2
99 24678 112.00 2
99 25405 273.50 2
99 25516 546.00 2
99 31000 783.00 2
99 31004 625.75 4
99 31005 1337.00 2
99 31032 461.00 1
99 32001 96.50 2
99 32004 119.50 2
99 32121 279.50 2
99 38105 6975.50 2
99 39206 294.00 2
99 39208 100.00 2
99 39230 40.00 2
99 7004 354.50 2
99 7100 307.00 2
99 7110 383.00 2
99 7160 108.00 2
99 7200 219.50 2
99 7255 447.00 2
99 7300 605.00 2
99 7601 210.50 2
99 7730 263.50 2
99 7741 191.50 2
99 NR 231.00 1

Pour simplifier les calculs, nous allons ignorer la variable région. Nous considérons donc que dans les différentes régions les aliments sont préparés de la même manière.

tbl_ci=tbl_acrylamide%>%
  mutate(ci=parse_character(acrylamide))%>%
  #créer une nouvelle variable ci à partir de
  #acrylamide mais avec un format character et non factor 
  mutate(ci=censure(ci,LOD=4,LOQ=10) )%>%
  #on applique la fonction censure qui remplace ND et NQ
  #par LOD et LOQ respectivement
  mutate(ci=parse_double(ci))%>%
  #transforme ci en format double
  group_by(codal)%>%
  summarise(`moyenne ci`=mean(10*ci,na.rm=TRUE),n=sum(table(codal))) 

Pour avoir les libellés des aliments, nous utiliserons la fonction mutate() et match()19 :

tbl_ci=tbl_ci%>%
  mutate(Aliment=
        tbl_acrylamide$lib[match(codal,tbl_acrylamide$codal)])

Tableau des moyennes des ci en mg/Kg

codal moyenne ci n Aliment
13038 40.00000 2 compote de pomme
13108 40.00000 2 compote de fruits autres que pomme
18002 217.64286 14 boisson au chocolat
18004 373.33333 3 café noir
18073 752.33333 15 café soluble reconstitué prêt à boire
20905 70.00000 2 dessert au soja nature
20909 40.00000 2 dessert au soja aux fruits
20911 40.00000 2 dessert au soja aromatisé au chocolat
23000 304.00000 2 gâteau
23455 179.00000 2 chou, chouquette
23499 304.00000 2 tarte ou tartelette
23585 481.50000 2 gâteau au chocolat
23800 232.00000 2 crêpe ou gaufre
23909 203.00000 2 cake aux fruits confits
23939 158.00000 3 moelleux au chocolat
24000 1929.50000 2 biscuit sec
24036 2127.50000 2 biscuit sec au chocolat
24678 112.00000 2 barquette à la pulpe de fruit
25009 119.50000 4 hachis parmentier
25019 123.33333 6 pâtes fourrées type ravioli
25089 338.50000 2 cordon bleu de volaille
25405 273.50000 2 quiche lorraine
25413 93.33333 6 hamburger
25516 546.00000 2 pizza
26030 135.68750 16 poisson pané
31000 783.00000 2 barre chocolatée biscuitée
31004 625.75000 4 chocolat au lait
31005 1337.00000 2 chocolat noir
31032 461.00000 1 pâte à tartiner chocolatée
32001 96.50000 2 céréales au chocolat
32004 119.50000 2 muesli
32121 279.50000 2 pétales de maïs
36004 100.00000 2 poulet
36306 160.50000 4 dinde escalope
38105 6975.50000 2 biscuit apéritif
39206 294.00000 2 mousse au chocolat rayon frais
39208 100.00000 2 chocolat viennois ou liégeois
39230 40.00000 2 crème dessert
4005 7240.93750 16 pomme de terre sautée ou frite
404 9544.62500 16 pomme de terre chips salées
7004 354.50000 2 pain grillé
7100 307.00000 2 pain de campagne
7110 383.00000 2 pain complet ou intégral
7160 108.00000 2 baguette
7200 219.50000 2 pain de mie
7255 447.00000 2 pain aux céréales
7300 605.00000 2 biscotte
7601 210.50000 2 croissant
7730 263.50000 2 pain au chocolat
7741 191.50000 2 brioche et pain brioché
92055 154.55556 9 sandwich
NR 231.00000 1 gateau moelleux fourré ou non

6.5 Travailler avec plusieurs tables (tibbles)

R permet de travailler avec plusieurs tables à la fois. Un des principaux intérêts d’une base de données est de pouvoir créer des relations entre les tables, de pouvoir les lier entre elles. Pour le moment, nous n’avons travaillé que sur une seule table à la fois. Dans la pratique, vous aurez certainement plusieurs tables dans votre base, dont la plupart seront interconnectées. Cela vous permettra de mieux découper vos informations, d’éviter des répétitions et de rendre ainsi vos données plus faciles à gérer.

Prenons un exemple simple où nous disposons de deux tables x et y, que nous allons saisir directement grâce à la fonction tribble()20. Ces deux tables sont interconnectées grâce à la variable key.

x <- tribble(
  ~key, ~val_x,
     1, "x1",
     2, "x2",
     3, "x3"
)
y <- tribble(
  ~key, ~val_y,
     1, "y1",
     2, "y2",
     4, "y3"
)

Si pour une valeur quelconque de y (par exemple y2) vous souhaitez obtenir sa correpondant dans le tableau x, vous auriez à faire une opération dite jointure.

Il existe plusieurs types de jointures, qui nous permettent de choisir exactement les données que l’on veut récupérer. Les plus importantes sont :

La jointure interne entre x et y :

x%>%
  inner_join(y,by="key")
## # A tibble: 2 × 3
##     key val_x val_y
##   <dbl> <chr> <chr>
## 1     1    x1    y1
## 2     2    x2    y2

La jointure externe peut être faite de trois façons différentes : gauche, droite ou totale. La figure suivante illustre les jointures externes.

Les différentes jointures externes

Les différentes jointures externes

left_join(x,y,by="key");right_join(x,y,by="key");full_join(x,y,by="key")
## # A tibble: 3 × 3
##     key val_x val_y
##   <dbl> <chr> <chr>
## 1     1    x1    y1
## 2     2    x2    y2
## 3     3    x3  <NA>
## # A tibble: 3 × 3
##     key val_x val_y
##   <dbl> <chr> <chr>
## 1     1    x1    y1
## 2     2    x2    y2
## 3     4  <NA>    y3
## # A tibble: 4 × 3
##     key val_x val_y
##   <dbl> <chr> <chr>
## 1     1    x1    y1
## 2     2    x2    y2
## 3     3    x3  <NA>
## 4     4  <NA>    y3

6.6 Exemple de calcul d’exposition

Nous cherchons à estimer l’exposition alimentaire à l’acrylamide. Le calcul d’exposition alimentaire à l’acrylamide (pour un individu j) est en général calculé selon la formule suivante:

\[E_{j}=\frac{\sum_{i=1}^{a}C_{i} Q_{ij}}{poids_{j}}\]

\(C_{i}\) est la concentration moyenne du contaminant(mg/kg) dans l’aliment i (i est l’indice des différents aliments) et \(Q_{ij}\) la quantité moyenne (en g) consommé par l’individu j de l’aliment i. La somme (\(\sum\)) est faite sur tous les aliments concernés (le nombre d’aliments est noté par a).

Les données nécessaires à ce calcul sont éclatées dans trois tableaux différents : tbl_indiv, tbl_ci et tbl_conso. Nous allons importer ensemble la troisième table. Elle renseigne les caractéristiques des individus interrogés sur leur consommation alimentaire. Vous avez remarqué sans doute l’existence d’une variable nommée au départ nomen que nous avons renommé en ID_indiv. Cette variable est un identifiant unique de chaque partcipant de l’étude. ID_indiv nous permettra de faire le lien entre certaines tables.

Nous allons maintenant importer la table “conso.csv”. Puis nous la transformons en tibble :

tbl_conso=as_data_frame(read.csv("consos.csv"))
tbl_conso%>%
  names()
## [1] "nomen"    "lib"      "codgr"    "sougr"    "codal"    "quantité"
tbl_conso=tbl_conso%>%
     rename(ID_indiv=nomen)
tbl_conso%>%
  names()
## [1] "ID_indiv" "lib"      "codgr"    "sougr"    "codal"    "quantité"

La variable nomen correspond à la variable ID_indiv le tibble tbl_indiv. La colonne lib donne le libellé de chaque aliment consommé durant la période de l’enquête. Les colonnes cdgr, et sougr donnent des codes uniques pour le groupe d’aliment, le sous groupe d’aliment auquel l’aliment appartient. La colonne codal est un code de l’aliment. La colonne quantité renseigne la quantité moyenne consommée par aliment (en g).

Exercice : calculez l’exposition à l’acrylamide à partir de ces trois tableaux .

7 Visualisation des données avec ggplot2

ggplot2 est package qui vous permettra de construire, pas à pas (ou par couches), des visualisations des plus simplistes aux plus perfectionnées. la construction de ce package a été fondée sur la grammaire de graphique de Leland Wilkinson21.
Le principe de ggplot2 est de construire le graphique par « couche ». Il existe cinq grandes familles de couches, que nous allons explorer pas à pas.

7.1 Les différentes couches de ggplot2

La première ligne d’un code ggplot2, la première couche, indique à la fonction ggplot() les données de base sur lesquelles s’appuieront toutes les couches suivantes. Les données doivent être organisées dans un data frame ou un tibble. Afin d’explorer le principe de fonctionnement de ggplot, créeons un data frame grâce aux fonctions de base de R:

x1=rnorm(100,50,5); y1=x1+rnorm(100,0,0.7)
x2=rnorm(150,60,7); y2=x2*0.8+rnorm(150,0,1)
x3=rnorm(200,40,4); y3=x3*1.2+rnorm(200,0,1.2)
x=c(x1,x2,x3)
y=c(y1,y2,y3)
population=rep(c("A","B","C"),c(100,150,200))
df=tibble(x,y,population)

Couche déclaration des données

ggplot(data=df)

A ce stade le résultat affiche uniquement un cadre vide.

Couche esthétique (aes)
La deuxième couche consiste à indiquer l’esthétique du graphique grâce à la fonction aes():

ggplot(data=df)+
  aes(x=x,y=y,colour=population, fill=population)

ggplot, couche data + couche aes

ggplot, couche data + couche aes

La syntaxe de la fonction aes():
aes(x = X, y = Y, colour = col, fill = fill, size = size)) — les éléments col, fill et size représentent respectivement les variables que vous souhaitez affecter aux couleurs, à la taille ou au remplissage de vos éléments. L’enchaînement des couches se fait en général avec “+”. Avec la couche aes() nous obenons un cadre avec les axes définis dans aes().

Couche géométrie « geom »

Cette couche permet de définir les éléments visuels qui représenteront vos données. C’est à cette étape que vous devrez choisir un geom (il en existe plus de 40) qui visualisera vos données : barres, points, histogramme… vous avez l’embarras du choix ! Pour commencer, choisissons des points.

ggplot(data=df)+
  aes(x=x,y=y,colour=population, fill=population)+
  geom_point()

ggplot, couche data + couche aes + couche geom

ggplot, couche data + couche aes + couche geom

Nous obtenons maintenant un graphique complet où les points prennent des couleurs différents selon la valeur de la variable population (ici une variable qualitative 1, 2 et 3).

Couche échelle « scale »

Cette couche vous permet de contrôler les paramètres d’affichage de votre visualisation, sur deux niveaux : les axes, et les projections des données. Autrement dit, vous pouvez définir les limites des axes, le format des chiffres utilisés sur ces axes, les couleurs et les échelles des axes…

Par exemple, nous pouvons changer l’échelle de couleur des points, et l’affichage d’éléments des axes :

ggplot(data=df)+
  aes(x=x,y=y,colour=population, fill=population)+
  geom_point()+
  scale_colour_manual(values = c( "#E66A41", "#88878C", "#A2C616"))+
  scale_x_continuous(limits = c(20, 60)) 

ggplot, couche data + couche aes + couche geom + couche scale

ggplot, couche data + couche aes + couche geom + couche scale

scale_x_continuous(name, breaks, labels, limits, trans)
scale_y_continuous(name, breaks, labels, limits, trans)

Les fonctions pour la transformations des axes sont:

Il est possible d’ajouter des graduations log en utilisant la fonction annotation_logticks().

Couche « facet »

Il est possible de visualiser vos graphiques selon différentes facettes. Cette couche vous permet de séparer votre fenêtre en plusieurs visualisations, selon un facteur défini. Par exemple :

ggplot(data=df)+
  aes(x=x,y=y,colour=population, fill=population)+
  geom_point()+
  facet_grid(. ~ population)

ggplot, utilisation d’une facette

ggplot, utilisation d'une facette

Couche thèmes

Cette couche vous permettra de choisir le « design » de vos visualisations. La fonction, qui commence par theme(), vous permet de personnaliser tous les éléments visuels : titres, tailles des axes, légende, couleur de fond… etc. Les possibilités de personnalisation du thème sont vastes. À noter que ggplot2 vient avec une dizaine de thèmes prédéfinis (9, pour être précis : puis theme_grey(), theme_gray(), theme_bw(), theme_linedraw(), theme_light(), theme_minimal(), theme_classic(), theme_dark(), theme_void()).

Par exemple:

 ggplot(data=df)+ 
  aes(x=x,y=y,colour=population, fill=population)+
  geom_point()+
  facet_grid(. ~ population)+
  theme_bw()

ggplot, application d’un thème

ggplot, application d'un thème

7.2 Exemples de visualisation des données avec ggplot

Histogramme

La table “croissance” est un jeu de données sur des taux de croissance de Listeria monocytogenes obsservés sur un aliment donnée.

df=readRDS("croissance.rda")
summary(df)
##   température    taux de croissance souche
##  Min.   : 5.00   Min.   :0.000000   1:55  
##  1st Qu.: 8.00   1st Qu.:0.005115   2:55  
##  Median :20.00   Median :0.035115   3:55  
##  Mean   :21.82   Mean   :0.056912   4:55  
##  3rd Qu.:35.00   3rd Qu.:0.096767   5:55  
##  Max.   :45.00   Max.   :0.214349

Pour un histogramme simple

   ggplot(data=df)+
   aes(x=`taux de croissance`)+
   geom_histogram()+
   ylab("Fréquence")+
    theme_bw()
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Histogramme avec ggplot

Histogramme avec ggplot

Le même histogramme peut être décliné en fonction des souches de L. monoytogenes testées.

ggplot(data=df)+
   aes(x=`taux de croissance`,coulour=souche,fill=souche)+
   geom_histogram()+
   ylab("Fréquence")+
   scale_x_continuous(breaks  = c(0, 0.10,0.20))+
   facet_grid(.~souche)
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Histogramme avec facette

Histogramme avec facette

Nuage de points avec tendance

La fonction geom_point vous permet de représenter les points de coordonnées (x,y). La fonction geom_smoothajoute une courbe de tendance (lissage des points).

ggplot(data=df)+
   aes(x=`température`,y=`taux de croissance`)+
   
   geom_point(aes(colour = souche))+
   geom_smooth()+
   theme_bw()

Nuage de points avec lissage

Nuage de points avec lissage

Même graphe mais par souche:

ggplot(data=df)+
   aes(x=`température`,y=`taux de croissance`)+
   
   geom_point(aes(colour = souche),size=0.5)+
   geom_smooth()+
   facet_grid( . ~ souche)+
   scale_x_continuous(breaks  = c(10,30))+
   theme_bw()

Nuage de points avec lissage at facette

Nuage de points avec lissage at facette

Boxplot

Pour tracer un “Boxplot”, il vous suffit d’ajouter geom_boxplot. Cependant, il faudra s’aasurer que dans la fonction aes() vous avez bien mentionné la variable qualittaive et la variable quantitative. Afin d’éviter la superposition des points, la fonction geom_jitter ajoute un bruit sur les données afin de les différencier sans nuire à la structure des données.

ggplot(df, aes(souche, `taux de croissance`,fill=souche))+
geom_boxplot()+
  geom_jitter(position = position_jitter(width = .2),size=.3) +
  theme_bw()

Boxplot avec ggplot

Boxplot avec ggplot

Vous pouvez choisir une forme de boîtes grâce à l’option notch=TRUE et même les présenter horizontalement:

ggplot(df, aes(souche, `taux de croissance`,fill=souche))+
geom_boxplot(notch=TRUE)+
  geom_jitter(position = position_jitter(width = .2),size=.3) +
  coord_flip()+
  theme_bw()

Boxplot en notch et inversion des coordonnées

Boxplot en notch et inversion des coordonnées

7.3 Densité de probabilité

df3=tibble(x=c(rnorm(100,50,10),rnorm(150,60,12),rnorm(200,40,15)),
           population=factor(rep(1:3,c(100,150,200))))
ggplot(data=df3)+
  aes(x,fill=population)+
  geom_histogram(aes(y = ..density..))
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
ggplot(data=df3)+
  aes(x,fill=population)+
  geom_density(alpha=0.5)+
  ylab("densité")

Densité de probabilité

Densité de probabilitéDensité de probabilité

7.4 Ajouter des équations mathématiques

Il est tout à fait possible d’utiliser des équations mathématiques au lieu des chaînes de caractères. Il suffit d’utiliser quote à la place de “” lorsque vous déclarer les labels des axes ou du titre. Pour connaître les options disponibles consulter ?plotmath (aide de plotmath). Voici un exemple de dose réponse : \[P(reponse)=1-\Big[1+\frac{dose}{\beta}\Big]^{-\alpha}\]

alpha=0.5
beta=118
dose=seq(0,6,0.1) # dose en log10
ld=10^dose
p=1-(1+ld/beta)^(-alpha)
dr=tibble(
  dose,
  `Probabilité d'infection`=p
)
ggplot(dr)+
  aes(x=dose,y=`Probabilité d'infection`)+
  geom_line()+
  labs(
    y=quote(1-(1+frac(dose,alpha))^-alpha)
  )+
  geom_text(x=4, y=0.5, label="beta==118",parse=T,size=5)+
  geom_text(x=4, y=0.6, label="alpha==0.5",parse=T,col="red")

Ajouter des symboles mathématiques

Ajouter des symboles mathématiques