Lors du nettoyage des données, on peut être amené à appliquer le même recodage à plusieurs variables aux modalités similaire (valeurs manquantes, Ne sait pas, Batterie de variables semblables, … ). Pour éviter de copier-coller un même code, on peut facilement automatiser le processus sur R.
Il existe plusieurs solutions pour automatiser un recodage dans R, nous allons aborder certaines d’entre-elles mais cette liste est loin d’être exhaustive.
Données d’exemple
On commence par créer un jeu de données, composé de 10 lignes et 10 colonnes, et qui contient des valeurs manquantes:
Dans le R de base, il est possible de recoder l’entiereté des occurences d’une certaines valeurs (ou les valeurs manquantes) pour l’ensemble du jeu de données.
Sur l’ensemble des données
Exemple 1 : Changer l’ensemble des valeurs manquantes
# Je fais un copie du jeu de donnéedf2<-df# Je remplace tous les NA par la valeurs 0df2[is.na(df2)]<-0df2
Les jeux de données peuvent être composés d’un grand nombre de variables et donc on peut-être amené à effectuer un recodage uniquement sur certaines variables.
L’exemple ci-dessous montre comment procéder à partir d’une sélection de variable stockée dans le vecteur var.
Exemple 3 : Recoder une sélection de variables
# Je fais une copie de l'originaldf2<-df# Je choisis certaines variables sur lesquelle on appliquera le recodagevar<-c("V1","V7","V9")# Fonctionne aussi avec la position de la colonne# var <- c(2,5,6)# On crée une boucle qui s'activera uniquement pour les variables contenues # dans varfor(iinvar){df2[[i]]<-ifelse(df2[[i]]==10, "DIX", df2[[i]])}df2
Seulement les variables V1, V7 et V9 ont été recodées. On remarque que des valeurs 10 sont présentes dans la variable V10.
Avec le package dplyrdu tidyverse :
Les boucles peuvent être complexe à prendre en main, et pas forcément conseillées dans R. Le package dplyr propose un ensemble de fonctions permettant de recoder plusieurs variables avec seule une fonction.
Sur l’ensemble des données
La fonction mutate_all permet de recoder l’ensemble des variables du jeu de données.
Le signe ~ est obligatoire, et permet d’indiquer qu’on applique la formule qui le suit à l’ensemble du jeu de données.
Les . sont une spécificité de la syntaxe sous forme de pipes (%>%). Ils sont synonymes de la base de données en entrée (df) mais permet de tenir compte de toutes les transformations des pipes précédentes faites sur cette base.
Sur une sélection de variables
Les fonctions mutate_if et mutate_at permettent d’appliquer un recodage mais uniquement sur des variables choisies par une ou plusieurs conditions.
Exemple 5 : mutate_if
Dans cet exemple, on va appliquer un recodage uniquement aux variables numériques. Pour l’exemple, on commence par créer une variable catégorielle var_categ, sur laquelle le recodage ne s’appliquera pas.
var_categ V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
1 bonjour 8 <NA> 8 CINQ 8 CINQ CINQ 8 6 1
2 5 3 4 8 9 7 7 6 6 6 9
3 bonjour 6 4 4 9 8 1 CINQ 3 2 NA
4 5 NA 9 4 CINQ 6 1 7 6 CINQ 10
5 bonjour 1 CINQ 1 3 7 CINQ 6 CINQ 1 10
6 5 6 9 9 3 CINQ CINQ 10 <NA> 9 9
7 bonjour 10 6 8 9 9 <NA> <NA> 4 10 9
8 5 1 8 NA 8 6 2 3 CINQ 9 7
9 bonjour 10 4 3 6 2 2 7 <NA> 6 9
10 5 2 4 2 CINQ 9 7 8 8 2 4
Exemple 6 : mutate_at
la fonction mutate_at permet d’appliquer un recodage à un ensemble de variables définies par leur nom.
Ici, on applique le recodage uniquement aux variables qui continennent la chaîne de caractéres V1 dans leur nom de variables, on recode donc V1 et V10.
# Sélection des variablesvar<-grep("1", names(df), value=TRUE)var
[1] "V1" "V10"
# On recode les NA en VAL.MANQ pour les variables de vardf2<-df%>%mutate_at(var, ~ifelse(is.na(.)==TRUE, "VAL.MANQ", .))df2
Automatisation de la création de nouvelles variables
Jusqu’ici nous avons vu comment recoder des variables existantes en changeant leurs valeurs, mais il est souvent préférable de créer de nouvelles variables pour éviter de perdre la variable originale.
Exemple 7 : Avec une boucle for et assign
Dans cet exemple, nous allons choisir 3 variables à recoder (“V1”,“V3”,“V5”), mais au lieu de les écraser avec leurs nouvelles valeurs nous allons créer des copies de ces variables qui porteront le suffixe bis.
Si l’opération peut sembler facile aux premier abord, créer des nouveaux objets et leur affecter automatiquement une nouvelle valeur pose un problème majeur dans R : Il n’est pas possible d’écrire une fonction devant un symbole d’affectation comme le = ou le <-
Cela signifie que pour créer de nouvelles variables, on ne peut pas écrire :
Pour contourner ce problème, on utilise la fonction assign(), qui contient deux arguments : assign(NOM_NV_OBJ, valeurs_prisent). On peut donc créer des variables avec des noms issues de fonctions comme paste. Dans notre cas on colle ANCIEN_NOM et bis.
Pour chercher cet objet stocké dans l’environnement et en faire une variable, on utilise la fonction get() qui permet d’utiliser des fonctions comme paste() pour récupérer les valeurs des objets crées automatiquement.
# Copie de l'originaldf2<-df# Sélecion des variablesvar<-c("V1","V3","V5")for(iinvar){assign(paste0(i,"_bis"), # Nom de l'objetifelse(df2[[i]]==8, "HUIT", df2[[i]])# Valeur qu'il prend)# On crée la variable à partir de l'objet crée au dessusdf2[paste0(i,"_bis")]<-get(paste0(i,"_bis"))}# On affiche la base avec les nouvelles variables en premièresdf2%>%select(contains("bis"), everything())
On a bien crée automatiquement de nouvelles variables, tout en conservant les anciennes.
Code source
---title: "Recodage multiple"# subtitle: ""categories: - Boucle - Recodageauthor: - name: "Arno Muller" affiliations: - name: "Ined"date: 06/28/2023image: "https://www.r-project.org/Rlogo.png"format: html: defaultfilters: - lightboxlightbox: autocode-annotations: belowabstract: | Lors du nettoyage des données, on peut être amené à appliquer le même recodage à plusieurs variables aux modalités similaire (valeurs manquantes, Ne sait pas, Batterie de variables semblables, ... ). Pour éviter de copier-coller un même code, on peut facilement automatiser le processus sur R. ---| Packages | Fonctions ||---------------|-----------------------------------------------------------------|| **dplyr** | `mutate_all` - `mutate_if` - `mutate_at` - `ifelse` - `select` || **Base R** | `as.data.frame` - `for` - `grep` - `assign` - `get` - `paste` |: **Fonctions utilisées dans la fiche**Il existe plusieurs solutions pour automatiser un recodage dans R, nous allons aborder certaines d'entre-elles mais cette liste est loin d'être exhaustive.# Données d'exempleOn commence par créer un jeu de données, composé de 10 lignes et 10 colonnes, et qui contient des valeurs manquantes:```{r}set.seed(1)df <-as.data.frame(matrix(sample(c(NA, 1:10), 100, replace =TRUE), 10))df```# Avec R de base :Dans le R de base, il est possible de recoder l'entiereté des occurences d'une certaines valeurs (ou les valeurs manquantes) pour l'ensemble du jeu de données.## Sur l'ensemble des données### Exemple 1 : Changer l'ensemble des valeurs manquantes```{r}# Je fais un copie du jeu de donnéedf2 <- df# Je remplace tous les NA par la valeurs 0df2[is.na(df2)] <-0df2```### Exemple 2 : Remplacer une valeur par une autre```{r}# Je fais une copie de l'originaldf2 <- df# Je remplace tous les 10 par la valeur "DIX"df2[df2==10] <-"DIX"df2```## Sur une sélection de variablesLes jeux de données peuvent être composés d'un grand nombre de variables et donc on peut-être amené à effectuer un recodage uniquement sur certaines variables.L'exemple ci-dessous montre comment procéder à partir d'une sélection de variable stockée dans le vecteur *var*.### Exemple 3 : Recoder une sélection de variables```{r}# Je fais une copie de l'originaldf2 <- df# Je choisis certaines variables sur lesquelle on appliquera le recodagevar <-c("V1","V7","V9")# Fonctionne aussi avec la position de la colonne# var <- c(2,5,6)# On crée une boucle qui s'activera uniquement pour les variables contenues # dans varfor (i in var) { df2[[i]] <-ifelse(df2[[i]] ==10, "DIX", df2[[i]])}df2```Seulement les variables V1, V7 et V9 ont été recodées. On remarque que des valeurs 10 sont présentes dans la variable V10.# Avec le package `dplyr`du tidyverse :Les boucles peuvent être complexe à prendre en main, et pas forcément conseillées dans R. Le package `dplyr` propose un ensemble de fonctions permettant de recoder plusieurs variables avec seule une fonction.## Sur l'ensemble des donnéesLa fonction `mutate_all` permet de recoder l'ensemble des variables du jeu de données.### Exemple 4 : **`mutate_all`**On remplace l'ensemble de 7 par la valeur "SEPT"```{r warning=FALSE, message=FALSE}library(dplyr)df2 <- df %>% mutate_all(~ifelse(. == 7, "SEPT", .))df2```- Le signe **`~`** est obligatoire, et permet d'indiquer qu'on applique la formule qui le suit à l'ensemble du jeu de données. - Les **`.`** sont une spécificité de la syntaxe sous forme de **pipes** (%>%). Ils sont synonymes de la base de données en entrée (df) mais permet de tenir compte de toutes les transformations des pipes précédentes faites sur cette base.## Sur une sélection de variablesLes fonctions `mutate_if` et `mutate_at` permettent d'appliquer un recodage mais uniquement sur des variables choisies par une ou plusieurs conditions.### Exemple 5 : `mutate_if`Dans cet exemple, on va appliquer un recodage uniquement aux variables numériques.Pour l'exemple, on commence par créer une variable catégorielle *var_categ*, sur laquelle le recodage ne s'appliquera pas.```{r}df2 <- df %>%mutate(var_categ =rep(c("bonjour", "5"), 5)) %>%select(var_categ, everything())df2```On utilise **`mutate_if`**, pour changer la valeur 5 en CINQ, uniquement pour les variables numériques.```{r}df2 <- df2 %>%mutate_if(is.numeric, ~ifelse(. ==5, "CINQ", .))df2```### Exemple 6 : **`mutate_at`**la fonction `mutate_at` permet d'appliquer un recodage à un ensemble de variables définies par leur nom. Ici, on applique le recodage uniquement aux variables qui continennent la chaîne de caractéres V1 dans leur nom de variables, on recode donc V1 et V10.```{r}# Sélection des variablesvar <-grep("1", names(df), value=TRUE)var# On recode les NA en VAL.MANQ pour les variables de vardf2 <- df %>%mutate_at(var, ~ifelse(is.na(.) ==TRUE, "VAL.MANQ", .))df2```# Automatisation de la création de nouvelles variablesJusqu'ici nous avons vu comment recoder des variables existantes en changeant leurs valeurs, mais il est souvent préférable de créer de nouvelles variables pour éviter de perdre la variable originale.### Exemple 7 : Avec une boucle **`for`** et **`assign`**Dans cet exemple, nous allons choisir 3 variables à recoder ("V1","V3","V5"), mais au lieu de les écraser avec leurs nouvelles valeurs nous allons créer des copies de ces variables qui porteront le suffixe *bis*.Si l'opération peut sembler facile aux premier abord, créer des nouveaux objets et leur affecter automatiquement une nouvelle valeur pose un problème majeur dans R : **Il n'est pas possible d'écrire une fonction devant un symbole d'affectation comme le = ou le <- **Cela signifie que pour créer de nouvelles variables, on ne peut pas écrire : ```{r eval =FALSE}# IMPOSSIBLEpaste0(V1, "_bis") <- ifelse(df$V1 == 8, "HUIT", df$V1)# IMPOSSIBLEdf$paste0(V1, "_bis")```Pour contourner ce problème, on utilise la fonction **`assign()`**, qui contient deux arguments : `assign(NOM_NV_OBJ, valeurs_prisent)`. On peut donc créer des variables avec des noms issues de fonctions comme `paste`. Dans notre cas on colle *ANCIEN_NOM* et *bis*.Pour chercher cet objet stocké dans l'environnement et en faire une variable, on utilise la fonction `get()` qui permet d'utiliser des fonctions comme `paste()` pour récupérer les valeurs des objets crées automatiquement.```{r}# Copie de l'originaldf2 <- df# Sélecion des variablesvar <-c("V1","V3","V5")for (i in var) {assign(paste0(i,"_bis"), # Nom de l'objetifelse(df2[[i]] ==8, "HUIT", df2[[i]]) # Valeur qu'il prend )# On crée la variable à partir de l'objet crée au dessus df2[paste0(i,"_bis")] <-get(paste0(i,"_bis"))}# On affiche la base avec les nouvelles variables en premièresdf2 %>%select(contains("bis"), everything())```On a bien crée automatiquement de nouvelles variables, tout en conservant les anciennes.