C'est de la data et mon expeRtise afin d'en tirer le maximum

8 fonctions pour la manipulation

Dans cet article, je vous présente, 8 fonctions très utiles, que j’utilise quasi quotidiennement pour analyser des données, et qui sont parfois méconnues ! Cet article est complémentaire à celui dédié à la manipulation de données avec le package dplyr. 👉 Accédez à l’article Manipulations de données avec le package dplyr   Certaines des fonctions décrites ici appartiennent également à ce package dplyr. Ce package rentre parfois en conflit avec d’autres packages déjà installés. Pour solutionner ces situations, je vous recommande de lire l’article “Un petit hack pour éviter les conflits de packages sous R” 👉 Accédez à l’article “Un petit hack pour éviter les conflits de packages sous R”  

1. La fonction pull()

La fonction `pull` appartient au package `dplyr` qui lui-même appartient au super package `tidyverse`. Elle permet d’extraire une colonne d’un data frame directement dans un vecteur.

Cette fonction est l’équivalent du `$` dans la commande `mydata$colonne`, mais elle a l’avantage d’être tidyverse compatible, et donc de pouvoir s’intégrer à une suite d’instructions.

Dans l’exemple ci-dessous, je filtre les données de l’espèce setosa, puis je calcule la surface des sépales, et j’extrais cette variable, grâce à la fonction `pull()`, pour la stocker dans un vecteur :

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

area<- iris %>%
    filter(Species=="setosa") %>% 
    mutate(area=Sepal.Length*Sepal.Width) %>% 
    pull(area)

# vérification
str(area)
##  num [1:50] 17.8 14.7 15 14.3 18 ...

# autre vérification
is.vector(area)
## [1] TRUE
 

Alors que si vous utilisez `select()` vous allez extraire un data.frame, et pas un vecteur ! Cela est moins pratique, car il faudra une seconde étape pour extraire uniquement la colonne d’intérêt.

area<- iris %>%
    filter(Species=="setosa") %>% 
    mutate(area=Sepal.Length*Sepal.Width) %>% 
    select(area)

# vérification
str(area)
## 'data.frame':    50 obs. of  1 variable:
##  $ area: num  17.8 14.7 15 14.3 18 ...
 

2. La fonction slice()

Cette fonction permet de filtrer des lignes, en fonction de leurs indices. Elle appartient également au package `dplyr`, elle peut donc s’intégrer à l’intérieur d’une suite de commandes, avec l’utilisation du pipe `%>%`.

En reprenant une partie de l’exemple précédent, je vais arranger les lignes dans l’ordre décroissant des surface de sépales, et ne conserver que les 5 plus grandes :

area_top5 <- iris %>%
    filter(Species=="setosa") %>% 
    mutate(area=Sepal.Length*Sepal.Width) %>% 
    arrange(desc(area)) %>% 
    slice(1:5)

area_top5
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species  area
## 1          5.7         4.4          1.5         0.4  setosa 25.08
## 2          5.8         4.0          1.2         0.2  setosa 23.20
## 3          5.5         4.2          1.4         0.2  setosa 23.10
## 4          5.7         3.8          1.7         0.3  setosa 21.66
## 5          5.2         4.1          1.5         0.1  setosa 21.32
  La fonction slice() permet également de filtrer des lignes discontinues. Dans l’exemple ci-dessous, les lignes 1, 50 et 100 :
iris  %>% 
    slice(c(1,50, 100))

##   Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
## 1          5.1         3.5          1.4         0.2     setosa
## 2          5.0         3.3          1.4         0.2     setosa
## 3          5.7         2.8          4.1         1.3 versicolor
La fonction slice() possède plusieurs variantes :
  • `slice_head()` qui permet d’extraire les premières lignes,
  • `slice_tail()` qui permet d’extraire les dernières lignes,
  • `slice_min()` qui permet d’extraire la ligne de la plus faible valeur d’une variable donnée,
  • `slice_max()` qui permet d’extraire la ligne de la plus forte valeur d’une variable donnée,
  • `slice_sample()` qui permet d’extraire un échantillon de lignes au hasard :
iris  %>% 
    slice_sample(n=5, replace=FALSE)

##   Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
## 1          5.4         3.0          4.5         1.5 versicolor
## 2          4.4         2.9          1.4         0.2     setosa
## 3          6.8         2.8          4.8         1.4 versicolor
## 4          7.7         3.8          6.7         2.2  virginica
## 5          4.4         3.2          1.3         0.2     setosa
Vous pouvez consulter l’aide pour avoir plus d’informations sur l’utilisation de ces fonctions slice_:
?slice
 

3. La fonction relocate()

Cette fonction permet de modifier l’ordre des colonnes d’un data frame. Elle a appartient également au package `dplyr`.

Dans l’exemple ci-dessous, je créé une second jeu de données iris (appelé iris2) en recopiant `iris`, mais en positionnant la colonne `Species` en première position :

iris2 <-iris %>% 
    relocate(Species, everything())

head(iris2)

##   Species Sepal.Length Sepal.Width Petal.Length Petal.Width
## 1  setosa          5.1         3.5          1.4         0.2
## 2  setosa          4.9         3.0          1.4         0.2
## 3  setosa          4.7         3.2          1.3         0.2
## 4  setosa          4.6         3.1          1.5         0.2
## 5  setosa          5.0         3.6          1.4         0.2
## 6  setosa          5.4         3.9          1.7         0.4
La fonction everything() permet de dire “et ensuite toutes les autres variables”.

Remarque : ce repositionnant est aussi possible avec la fonction `select()`, mais la fonction `relocate()` offre plus de possibilités. Par exemple, ici de positionner `Species` après la variable `Sepal.Width`, grâce à l’argument `.after`.

iris3 <-iris %>% 
    relocate(Species, .after=Sepal.Width)

# vérification
head(iris3)
##   Sepal.Length Sepal.Width Species Petal.Length Petal.Width
## 1          5.1         3.5  setosa          1.4         0.2
## 2          4.9         3.0  setosa          1.4         0.2
## 3          4.7         3.2  setosa          1.3         0.2
## 4          4.6         3.1  setosa          1.5         0.2
## 5          5.0         3.6  setosa          1.4         0.2
## 6          5.4         3.9  setosa          1.7         0.4
  Pour plus de détails, consulter l’aide :
?relocate
 

4. La fonction count()

Cette fonction appartient toujours au package `dplyr`, elle permet d’obtenir le nombre de lignes correspondant à une condition ou une combinaison de condition. Comme elle est tidyverse compatible, elle est très utile en combinaison avec la fonction `group_by()`.

Par exemple, si je veux connaître, dans le jeu de données `heart_disease` (du package `funModelling`), combien de lignes correspondent aux croisement des modalité `has_heart_disease` et `gender` :

 
library(funModeling)

heart_disease %>% 
    group_by(has_heart_disease, gender) %>% 
    count()
## # A tibble: 4 x 3
## # Groups:   has_heart_disease, gender [4]
##   has_heart_disease gender     n
##   <fct>             <fct>  <int>
## 1 no                female    72
## 2 no                male      92
## 3 yes               female    25
## 4 yes               male     114
 

5. La fonction if_else()

Je me sers souvent de la fonction `if_else()` pour créer une variable catégorielle à partir d’une variable numérique. Dans l’exemple ci-dessous, je crée une variable `grp` qui prend pour valeur “low” si la longueur du pétale est inférieure à la médiane, et “high” sinon.

median(iris$Petal.Length)
## [1] 4.35

iris <- iris %>% 
    mutate(grp=ifelse(Petal.Length<=4.35, "low", "high"))

# vérification
iris %>% 
    slice_sample(n=10, replace=FALSE)

##    Sepal.Length Sepal.Width Petal.Length Petal.Width    Species  grp
## 1           5.1         3.4          1.5         0.2     setosa  low
## 2           4.9         2.5          4.5         1.7  virginica high
## 3           6.0         2.2          4.0         1.0 versicolor  low
## 4           5.0         3.2          1.2         0.2     setosa  low
## 5           6.7         3.0          5.2         2.3  virginica high
## 6           5.0         3.0          1.6         0.2     setosa  low
## 7           7.4         2.8          6.1         1.9  virginica high
## 8           6.5         3.2          5.1         2.0  virginica high
## 9           6.8         2.8          4.8         1.4 versicolor high
## 10          7.6         3.0          6.6         2.1  virginica high
  Et pour faire 3 catégories, il suffit d’emboîter deux if_else(), comme ceci :
iris <- iris %>% 
    mutate(grp=ifelse(Petal.Length<=4.35, "low", 
                      ifelse(Petal.Length<=5.1, "med", "high")))

# on vérifie
iris %>% 
    slice_sample(n=10, replace=FALSE)
##    Sepal.Length Sepal.Width Petal.Length Petal.Width    Species  grp
## 1           6.5         3.0          5.5         1.8  virginica high
## 2           5.1         3.5          1.4         0.2     setosa  low
## 3           4.6         3.2          1.4         0.2     setosa  low
## 4           6.7         3.1          4.7         1.5 versicolor  med
## 5           5.2         4.1          1.5         0.1     setosa  low
## 6           6.1         3.0          4.9         1.8  virginica  med
## 7           5.0         2.0          3.5         1.0 versicolor  low
## 8           5.1         3.8          1.6         0.2     setosa  low
## 9           6.1         2.8          4.7         1.2 versicolor  med
## 10          5.1         3.8          1.5         0.3     setosa  low
 

6. La fonction droplevels()

Cette fonction permet de retirer de la mémoire de R un ou plusieurs niveaux d’une variable catégorielle, qui ne sont plus employés. Par exemple, si je créé un sous-jeu de données ne contenant plus que les espèces `setosa`et `virginica` et que je consulte les niveaux de la variables `Species`, alors les 3 niveaux d’origine vont être affichés : `setosa`, `virginica`, et `versicolor`.

La fonction `droplevels`, permet de retirer (de la mémoire) le niveau `versicolor`:

# création du sous groupe de données
seto_virgi <- iris %>% 
    filter(Species %in% c("setosa", "virginica"))

# consultation des niveaux de la variable Species
levels(seto_virgi$Species)
## [1] "setosa"     "versicolor" "virginica"

# on retire les niveaux absents
seto_virgi$Species <- droplevels(seto_virgi$Species)

# vérification
levels(seto_virgi$Species)
## [1] "setosa"    "virginica"

La fonction `fct_drop()` du package `forcats` (qui appartient au package `tidyverse`), permet de faire exactement la même chose, lorsqu’elle est employée dans une fonction `mutate()` :

seto_versi <- iris %>% 
        filter(Species %in% c("setosa", "virginica")) %>%
        mutate(Species = fct_drop(Species))
        
# verification
levels(seto_versi$Species)
## [1] "setosa"    "virginica"
 

7. La fonction recode()

La fonction recode() peut être employée pour recoder les niveaux d’une variable catégorielle. Par exemple, si je souhaite recoder :
  •  “setosa” en “seto”
  • “virginica” et “virgi”
  • “versicolor” en “versi”
iris5 <- iris %>% 
    mutate(Species=recode(Species,
                setosa="set", 
                virginica="virgi", 
                versicolor="versi"))
# vérification
levels(iris5$Species)   
## [1] "set"   "versi" "virgi"
   

8. Les fonctions str_to_lower(), str_to_upper et str_to_title

Lorsque j’importe des données et qu‘il n’y a pas d’homogénéité dans le nommage des variables (certaines sont écrites en minuscule, d’autre en majuscule), j’utilise ces fonctions pour uniformiser les noms. Elles appartiennent au package `stringr` qui appartient au super package `tidyverse`. Voici un exemple avec le jeu de données `hall.fame` contenu dans le package `UsingR` :

library(UsingR)
names(hall.fame)
##  [1] "first"                   "last"                   
##  [3] "seasons"                 "games"                  
##  [5] "AB"                      "runs"                   
##  [7] "hits"                    "doubles"                
##  [9] "triples"                 "HR"                     
## [11] "RBI"                     "BB"                     
## [13] "SO"                      "BA"                     
## [15] "OBP"                     "SP"                     
## [17] "AP"                      "BR"                     
## [19] "ABRuns"                  "Runs.Created"           
## [21] "SB"                      "CS"                     
## [23] "Stolen.Base.Runs"        "Fielding.Average"       
## [25] "Fielding.Runs"           "Primary.Position.Played"
## [27] "Total.Player.Rating"     "Hall.Fame.Membership"

Nous pouvons voir que certains noms sont en majuscule, d’autres en minuscule, et d’autre encore comporte une majuscule sur la première lettre. Dans un premier temps, nous pouvons passer tous les noms en minuscule à l’aide de la fonction `str_to_lower()`:

 
names(hall.fame) <- str_to_lower(names(hall.fame))

# vérification
names(hall.fame)
##  [1] "first"                   "last"                   
##  [3] "seasons"                 "games"                  
##  [5] "ab"                      "runs"                   
##  [7] "hits"                    "doubles"                
##  [9] "triples"                 "hr"                     
## [11] "rbi"                     "bb"                     
## [13] "so"                      "ba"                     
## [15] "obp"                     "sp"                     
## [17] "ap"                      "br"                     
## [19] "abruns"                  "runs.created"           
## [21] "sb"                      "cs"                     
## [23] "stolen.base.runs"        "fielding.average"       
## [25] "fielding.runs"           "primary.position.played"
## [27] "total.player.rating"     "hall.fame.membership"
Nous pouvons ensuite, dans un second temps, ajouter une Majuscule à la première lettre, en employant la fonction str_to_title():
names(hall.fame) <- str_to_title(names(hall.fame))

# vérification
names(hall.fame) 
##  [1] "First"                   "Last"                   
##  [3] "Seasons"                 "Games"                  
##  [5] "Ab"                      "Runs"                   
##  [7] "Hits"                    "Doubles"                
##  [9] "Triples"                 "Hr"                     
## [11] "Rbi"                     "Bb"                     
## [13] "So"                      "Ba"                     
## [15] "Obp"                     "Sp"                     
## [17] "Ap"                      "Br"                     
## [19] "Abruns"                  "Runs.created"           
## [21] "Sb"                      "Cs"                     
## [23] "Stolen.base.runs"        "Fielding.average"       
## [25] "Fielding.runs"           "Primary.position.played"
## [27] "Total.player.rating"     "Hall.fame.membership"
 

Conclusion

J’espère que cet article vous aura permis de découvrir au moins une nouvelle fonction parmi les 8 décrites !

Et vous, est ce que vous avez une super fonction, que vous utilisez très souvent, et qui est méconnue ? Si oui, s’il vous plaît, partagez là en commentaire !

Merci !

Et si cet article vous a plu, ou vous a été utile, et si vous le souhaitez, vous pouvez soutenir ce blog en faisant un don sur sa page Tipeee 🙏 Soutenez Statistiques et logiciel R sur Tipeee  

Poursuivez votre lecture:

  Image par Hebi B. de Pixabay 

10 réponses

  1. bonjour,
    merci pour vos articles toujours intéressants et agréable à lire
    une fonction que je trouve bien pratique est clean_names() du package janitor qui permet d’hamoniser facilement les noms de colonnes ( par ex en supprimant les accents , les espaces..) lors d’import de fichier de données

    ex:
    library (janitor)

    df % clean_names(“snake”)
    df

    A tibble: 1 x 1

    elongation_du_parametre

    1 1

    il existe d’autres valeurs de paramètre autre que “snake” il suffit de regarder l’aide
    bonne journée

  2. Merci pour ces astuces !

    Pour ma part, j’ai découvert il n’y a pas si longtemps les packages questionr et esquisse … Je les partage toujours aux stagiaires et aux collègues qui ne sont pas des grands adeptes de R et c’est le succès à tous les coups 🙂

    1. Bonjour,

      Moi aussi j’ai découvert questionnr il y a peu, et c’est vrai qu’il est utile. J’en ferai peut être un sujet d’article…
      Bonne continuation

  3. Bonjour, merci pour ces infos super pratiques. J’avoue que je n’utilise pas les fonctions slice() et relocate(). J’aime beaucoup la fonction case_when() pour recoder des variables en facteurs car je la trouve plus facile à expliciter que des multiples if_else lorsque j’ai plusieurs catégories.
    Super info pour les fonctions de stringr auxquelles je pense trop peu.
    Toujours pratico-pratique ces conseils sont supers!

  4. BRAVO, c’est limpide, et tellement utile ! On peut ressortir les fiches le jour où on utilise R, car c’est une des difficultés de l’utilisateur lambda : R est nécessaire pour traiter une question,puis on peut ne pas l’utiliser pendant des semaines. Savoir qu’il existe cette reference est d’une grande aide

  5. Merci pour cet article ! (et ce blog d’une manière générale)

    Je me permets de suggérer 2 variantes :

    5 : dplyr::case_when

    iris %<>% mutate(grp = case_when(Petal.Length <= 4.35 ~ “low”,
    Petal.Length > 5.1 ~ “high”,
    TRUE ~ “med”))

    6 : Je trouve que c’est encore plus lisible en utilisant le %<>% de magrittr

    seto_virgi$Species %<>% droplevels()

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Bonjour !

vous venez souvent ?

Identifiez-vous pour avoir accès à toutes les fontionnalités !

Aide mémoire off'R ;)

Enregistrez vous pour recevoir gratuitement mes fiches “aide mémoire” (ou cheat sheets) qui vous permettront de réaliser facilement les principales analyses biostatistiques avec le logiciel R et pour être informés des mises à jour du site.