sd(dat[, 4])
[1] 5.457152
Voyons à présent quelques opérations basiques dans le dataframe importé dans la section précédente.
Dans le jeu de données précédemment importé, imaginons que l’on veuille calculer l’écart-type (fonction sd()
) de la variable TM6
, qui est en colonne 4. Il existe plusieurs façons équivalentes de procéder.
En utilisant le numéro de colonne :
sd(dat[, 4])
[1] 5.457152
En utilisant le nom de la colonne :
sd(dat[, "TM6"])
[1] 5.457152
En utilisant la syntaxe $
:
sd(dat$TM6)
[1] 5.457152
Il existe de nombreuses manières différentes d’accéder à une colonne donnée d’un dataframe. On peut aussi utiliser la fonction with()
, qui permet de spécifier en amont le jeu de données sur lequel on travaille (cela s’avère utile s’il y a de nombreuses instructions derrière, afin de ne pas avoir à rattacher le nom du jeu de données à chaque variable à laquelle on fait appel) :
with(dat, sd(TM6))
[1] 5.457152
Calculons maintenar l’écart-type de la variable FM1
:
sd(dat$FM1) # un essai "naïf" (mais naturel !)
[1] NA
Par défaut, de nombreuses fonctions R (mean()
, max()
, sd()
, etc.) retournent NA
si on leur soumet un vecteur comprenant des données manquantes. Pour forcer le calcul, on peut utiliser l’argument na.rm = TRUE
(cf. l’aide) :
sd(dat$FM1, na.rm = TRUE)
[1] 26.08093
Si on veut supprimer tous les individus incomplets (i.e. comportant au moins une valeur manquante) dans un dataframe, on utilise na.omit()
… mais cela peut être radical !
<- na.omit(dat)
net summary(net)
Site Sexe FM1 TM6 RM1 Hypoplasie
A:20 F:16 Min. :393.7 Min. :37.34 Min. :207.3 Non:31
B:16 M:20 1st Qu.:409.9 1st Qu.:44.23 1st Qu.:222.6 Oui: 5
Median :428.5 Median :48.88 Median :231.4
Mean :430.9 Mean :48.63 Mean :233.2
3rd Qu.:444.7 3rd Qu.:51.71 3rd Qu.:244.2
Max. :508.9 Max. :59.53 Max. :257.1
Presence_parure Orientation_corps
Non:22 Est :13
Oui:14 Nord : 7
Ouest:10
Sud : 6
Pour ajouter une nouvelle variable dans un dataframe, on la déclare “comme si elle existait déjà”, en spécifiant simplement l’opération qui la définit :
$Somme <- dat$FM1 + dat$RM1
dathead(dat) # visualiser le résultat
Site Sexe FM1 TM6 RM1 Hypoplasie Presence_parure Orientation_corps
A_1 A M 420.11 51.75 251.15 Non Non Nord
A_2 A M 508.93 57.98 255.82 Non Non Nord
A_3 A M 465.19 53.36 251.41 Non Non Est
A_4 A F 425.74 49.27 244.36 Oui Oui Ouest
A_5 A M 465.42 59.53 251.21 Non Non Est
A_6 A M 426.22 52.55 242.83 Non Non Est
Somme
A_1 671.26
A_2 764.75
A_3 716.60
A_4 670.10
A_5 716.63
A_6 669.05
Par défaut, la variable est toujours ajoutée en dernière colonne (il est toujours possible de réordonner ensuite).
Pour supprimer une variable, on la remplace par NULL
(attention : ce n’est pas équivalent à la remplacer par NA
!) :
$Somme <- NULL
dathead(dat) # la variable a bien disparu
Site Sexe FM1 TM6 RM1 Hypoplasie Presence_parure Orientation_corps
A_1 A M 420.11 51.75 251.15 Non Non Nord
A_2 A M 508.93 57.98 255.82 Non Non Nord
A_3 A M 465.19 53.36 251.41 Non Non Est
A_4 A F 425.74 49.27 244.36 Oui Oui Ouest
A_5 A M 465.42 59.53 251.21 Non Non Est
A_6 A M 426.22 52.55 242.83 Non Non Est
Il est possible de “filtrer” (en lignes) un dataframe selon un ou plusieurs critères en utilisant la fonction subset()
. Essayer et interpréter les instructions suivantes (demander éventuellement un summary()
de chaque sous-ensemble créé) :
## Filtrer sur une modalité d'un facteur :
<- subset(dat, Sexe == "F")
femmes print(femmes)
## Filtrer selon les modalités de deux facteurs :
<- subset(dat, Sexe == "F" & Site == "A")
femmes_A print(femmes_A)
## Filtrer selon *plusieurs* modalités d'un facteur :
<- subset(
est_sud
dat,%in% c("Est", "Sud")
Orientation_corps
)print(est_sud)
## Filtrer selon une variable numérique :
<- subset(dat, FM1 > 445)
grands print(grands)
Symbole | Sens logique |
---|---|
& |
“et” |
| |
“ou” |
%in% |
\(\in\), “appartient à” |
! |
“non”, négation logique |
!= |
\(\neq\), “n’est pas égal à” |
<= |
\(\leq\) |
>= |
\(\geq\) |
R étant en soi un langage assez ancien, et ayant à l’origine été conçu en partie par des mathématiciens plutôt que par des informaticiens, son design peut parfois être un peu daté par rapport aux langages de programmation plus modernes, comme Julia.
Le “tidyverse” est une collection de packages créés par l’entreprise Posit, et visant à introduire un “mini-langage” plus moderne à l’intérieur du langage R. Ses concepts sont abondamment documentés dans Wickham et al. (2023) et sur le site web dédié.
En particulier, le “tidyverse” inclut le package {dplyr}
, qui facilite un certain nombre d’opérations de manipulations de données, et où chaque fonction est un verbe très explicite.
Pour charger le package{dplyr}
, et plus généralement le meta-package {tidyverse}
:
library(tidyverse)
Parfois, comme ici, cela ne change pas grand chose par rapport aux fonctions R de base :
## Sélectionner un sous-ensemble d'individus (p. ex., les femmes) :
subset(dat, Sexe == "F") # fonction R de base
filter(dat, Sexe == "F") # équivalent dplyr
mais parfois, cela introduit au contraire une syntaxe beaucoup plus commode à manipuler, comme ci-dessous :
## Sélectionner des variables en spécifiant leur nom :
<- dat[ , c("FM1", "TM6", "RM1")] # R-base
num <- select(dat, FM1, TM6, RM1) # équivalent dplyr
num head(num)
Le package {dplyr}
, et les autres packages du “tidyverse”, seront ponctuellement utilisés d’ici la fin de la formation. N’hésitez pas à consulter la documentation pour découvrir davantage de fonctionnalités !
Nous venons de voir une instruction pour sélectionner certaines variables en spécifiant leur nom. Mieux encore, on peut aisément sélectionner toutes les variables d’un certain type dans le jeu de données : par exemple, toutes les variables numériques. Avec {dplyr}
, c’est presque immédiat :
<- select(dat, where(is.numeric))
num head(num)
FM1 TM6 RM1
A_1 420.11 51.75 251.15
A_2 508.93 57.98 255.82
A_3 465.19 53.36 251.41
A_4 425.74 49.27 244.36
A_5 465.42 59.53 251.21
A_6 426.22 52.55 242.83
En R-base, cela aurait nécessité une syntaxe nettement moins lisible et agréable, telle que :
<- unlist(lapply(dat, is.numeric))
bool_num <- dat[, bool_num] num
Pour réordonner toutes les lignes d’un dataframe selon les valeurs d’une variable donnée, on peut utiliser la fonction de base order()
pour retrier les lignes du tableau :
<- dat[order(dat$TM6), ]
triBase head(triBase)
ou bien, de façon plus explicite là encore, la fonction arrange()
du package {dplyr}
:
<- arrange(dat, TM6)
triDplyr head(triDplyr)
Site Sexe FM1 TM6 RM1 Hypoplasie Presence_parure Orientation_corps
B_5 B F NA 36.13 223.80 Non Non Est
B_16 B F 401.72 37.34 229.78 Non Oui Nord
B_7 B <NA> 428.41 40.66 200.69 Non Non Sud
B_14 B F 410.32 40.85 209.79 Non Oui Ouest
B_11 B F NA 41.91 226.28 Non Oui Sud
B_12 B F 393.67 42.33 222.92 Non Non Sud
Exercice. En consultant l’aide de ces fonctions :
TM6
?arrange()
, comment trier selon plusieurs variables (pour départager de possibles égalités) : selon TM6
puis selon FM1
?L’instruction apply()
permet d’appliquer la même fonction à toutes les lignes ou toutes les colonnes d’une matrice. L’argument MARGIN = 1
permet d’agir sur les lignes ; et MARGIN = 2
agit sur les colonnes.
On rappelle qu’on a précédemment défini un objet R num
, contenant uniquement les variables numériques du jeu de données. Il est donc assimilable à une matrice. Consultons-le à nouveau :
head(num)
FM1 TM6 RM1
A_1 420.11 51.75 251.15
A_2 508.93 57.98 255.82
A_3 465.19 53.36 251.41
A_4 425.74 49.27 244.36
A_5 465.42 59.53 251.21
A_6 426.22 52.55 242.83
Pour calculer l’écart-type de toutes les colonnes de ce nouveau tableau (attention aux données manquantes !) :
apply(num, MARGIN = 2, FUN = sd, na.rm = TRUE)
FM1 TM6 RM1
26.080928 5.457152 14.573473
{purrr}
Le package {purrr}
, qui fait partie du “tidyverse”, propose de nombreuses fonctions, rapides et explicites, pour itérer efficacement des opérations en R en une seule instruction. Les fonctions de {purrr}
, qui ont presque toutes un nom commençant par map_*()
, ont vocation à remplacer la fonction apply()
et ses fonctions dérivées en R.
Par exemple :
map_dbl(.x = num, .f = \(x) sd(x, na.rm = TRUE))
FM1 TM6 RM1
26.080928 5.457152 14.573473
Notez aussi, dans le bloc ci-dessus, la définition d’une fonction anonyme.
Il est possible d’écrire dans un fichier (par exemple un fichier CSV ou TXT) le contenu d’un dataframe, à l’aide des fonctions write.table()
, write.csv()
, ou encore write.csv2()
. On pourra consulter l’aide de chaque fonction pour connaître leurs particularités et leurs arguments par défaut.
Par exemple, pour exporter le dataframe net
créé dans la Section 7.2, on exécutera :
write.csv2(net, "./output/donnees_nettoyees.csv")
Puisqu’on a spécifié un chemin relatif vers ce fichier, il sera écrit dans un sous-dossier output
du répertoire courant de la session.