Programmer en R/Manipuler un tableau de données

Un livre de Wikilivres.

En R, les données tabulaires sont généralement modélisées dans des tableaux de données (data.frame). Un tableau de données est une liste dont tous les éléments sont des vecteurs de même taille.

La librairie tibble introduit une nouvelle classe pour les tableaux de données. Les tibbles se comportent exactement comme les data.frame mais leurs options d'impression par défaut sont différentes[1].

Développée par Hadley Wickham, la librarie dplyr a pour objectif de définir une grammaire pour la manipulation de données. Cette grammaire repose sur quelques verbes simples :

  • select() permet de sélectionner les colonnes d'un jeu de données ;
  • filter() permet de filtrer 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.

La librairie dplyr contient aussi la fonction group_by() qui permet d'effectuer chaque opération sur des sous-groupes du jeu de données.

La librairie tidyr permet de mettre en forme un jeu de données en passant notamment des données dont les valeurs sont réparties sur plusieurs colonnes dans un format long de type clé-valeur et inversement des données sous forme clé-valeur dans un format large[2]. La librarie tidyr contient donc essentiellement deux fonctions :

  • la fonction gather pour passer en mode clé-valeur
  • la fonction spread pour passer en mode large

Pré-requis[modifier | modifier le wikicode]

Pour cette section, il faut avoir installé dplyr.

library(tibble)
library(tidyr)
library(dplyr)

Exemples[modifier | modifier le wikicode]

Dans cette section, nous prenons comme exemple le fichier des députés déposé par l'association Wikimédia France sur la plateforme data.gouv.fr[3]. Ce fichier est au format CSV. Pour l'importer, on utilise la fonction read_csv() de la librairie readr. Pour en savoir plus sur l'import des fichiers CSV, on peut consulter la page Importer un fichier CSV.

library(readr)
table_deputes <- read_csv("data/deputes.csv")

Afficher un aperçu[modifier | modifier le wikicode]

  • La fonction glimpse() permet d'afficher un aperçu du tableau de données avec le nombre d'observations, le nombre de variables, le nom, le type et les premières valeurs de chacune des colonnes.
  • La fonction str() produit un résultat similaire
  • La fonction head() permet d'afficher les premières lignes d'un tableau de données
> table_deputes %>%
+   glimpse()
Observations: 575
Variables: 10
$ nom             <chr> "François Fillon", "François de Rugy", "Hervé Gaymard", "Aurélie Filipp...
$ genre           <chr> "masculin", "masculin", "masculin", "féminin", "féminin", "féminin", "m...
$ prenom          <chr> "François", "François", "Hervé", "Aurélie", "Delphine", "Marion", "Jacq...
$ nom_famille     <chr> "Fillon", "de Rugy", "Gaymard", "Filippetti", "Batho", "Maréchal-Le Pen...
$ date_naissance  <dttm> 1954-03-04, 1973-12-06, 1960-05-31, 1973-06-17, 1973-03-23, 1989-12-10...
$ lieu_naissance  <chr> "Le Mans", "Nantes", "Bourg-Saint-Maurice", "Villerupt", "Paris", "Sain...
$ circonscription <chr> "deuxième circonscription de Paris", "première circonscription de la Lo...
$ sycomore_id     <int> 3009, 17282, 3322, 17302, 17264, 18477, 921, 17275, 476, 17280, 1300, 1...
$ wikidata        <chr> "http://www.wikidata.org/entity/Q101410", "http://www.wikidata.org/enti...
$ frwiki          <chr> "https://fr.wikipedia.org/wiki/Fran%C3%A7ois%20Fillon", "https://fr.wik...

Parcourir les données[modifier | modifier le wikicode]

Pour parcourir les données, on utilise la fonction View().

table_deputes %>% View()

Filtrer les lignes[modifier | modifier le wikicode]

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

Par exemple, sur la table des députés, on peut filtrer la table pour ne garder que les députés de genre féminin :

> table_deputes %>%
+   filter(genre == "féminin")
# A tibble: 150 × 10
                          nom   genre        prenom       nom_famille date_naissance
                        <chr>   <chr>         <chr>             <chr>         <dttm>
1          Aurélie Filippetti féminin       Aurélie        Filippetti     1973-06-17
2              Delphine Batho féminin      Delphine             Batho     1973-03-23
3      Marion Maréchal-Le Pen féminin        Marion   Maréchal-Le Pen     1989-12-10
4            Michèle Delaunay féminin       Michèle          Delaunay     1947-01-08
5         Marie-George Buffet féminin  Marie-George            Buffet     1949-05-07
6               Valérie Boyer féminin       Valérie             Boyer     1962-06-11
7                Sylvia Pinel féminin        Sylvia             Pinel     1977-09-28
8      Marie-Arlette Carlotti féminin Marie-Arlette          Carlotti     1952-01-21
9  Nathalie Kosciusko-Morizet féminin      Nathalie Kosciusko-Morizet     1973-05-14
10              Cécile Duflot féminin        Cécile            Duflot     1975-04-01
# ... with 140 more rows, and 5 more variables: lieu_naissance <chr>, circonscription <chr>,
#   sycomore_id <int>, wikidata <chr>, frwiki <chr>

On peut aussi combiner plusieurs conditions. Dans l'exemple suivant, on filtre les députés de genre féminin dont l'année de naissance est postérieure à 1976. On utilise la fonction year() de la librairie lubridate() pour extraire l'année de la date de naissance.

library(lubridate)
> table_deputes %>%
+   filter(genre == "féminin", year(date_naissance) >= 1976)
# A tibble: 9 × 10
                       nom   genre    prenom     nom_famille date_naissance        lieu_naissance
                     <chr>   <chr>     <chr>           <chr>         <dttm>                 <chr>
1   Marion Maréchal-Le Pen féminin    Marion Maréchal-Le Pen     1989-12-10 Saint-Germain-en-Laye
2             Sylvia Pinel féminin    Sylvia           Pinel     1977-09-28               L'Union
3            Seybah Dagoma féminin    Seybah          Dagoma     1978-06-09                Nantes
4 Stéphanie Pernod-Beaudon féminin Stéphanie  Pernod-Beaudon     1978-10-13       Bourg-en-Bresse
5     Fanélie Carrey-Conte féminin   Fanélie    Carrey-Conte     1980-05-16                Bègles
6            Paola Zanetti féminin     Paola         Zanetti     1976-09-01              Créhange
7     Virginie Duby-Muller féminin  Virginie     Duby-Muller     1979-08-16            Bonneville
8            Marie Le Vern féminin     Marie         Le Vern     1983-01-11        Bois-Guillaume
9           Marine Brenier féminin    Marine         Brenier     1986-08-11                  Nice
# ... with 4 more variables: circonscription <chr>, sycomore_id <int>, wikidata <chr>, frwiki <chr>

La fonction slice() permet de filtrer un tableau de données en fonction des numéros de ligne.

> table_deputes %>% slice(1:10)
# A tibble: 10 × 10
                      nom    genre    prenom     nom_famille date_naissance        lieu_naissance
                    <chr>    <chr>     <chr>           <chr>         <dttm>                 <chr>
1         François Fillon masculin  François          Fillon     1954-03-04               Le Mans
2        François de Rugy masculin  François         de Rugy     1973-12-06                Nantes
3           Hervé Gaymard masculin     Hervé         Gaymard     1960-05-31   Bourg-Saint-Maurice
4      Aurélie Filippetti  féminin   Aurélie      Filippetti     1973-06-17             Villerupt
5          Delphine Batho  féminin  Delphine           Batho     1973-03-23                 Paris
6  Marion Maréchal-Le Pen  féminin    Marion Maréchal-Le Pen     1989-12-10 Saint-Germain-en-Laye
7         Jacques Bompard masculin   Jacques         Bompard     1943-02-24           Montpellier
8           Xavier Breton masculin    Xavier          Breton     1962-11-25                Darney
9      Christian Bataille masculin Christian        Bataille     1946-05-13    Rieux-en-Cambrésis
10       Michèle Delaunay  féminin   Michèle        Delaunay     1947-01-08      Clermont-Ferrand
# ... with 4 more variables: circonscription <chr>, sycomore_id <int>, wikidata <chr>, frwiki <chr>

Sélectionner des variables[modifier | modifier le wikicode]

La fonction select() permet de sélectionner les colonnes d'un tableau de données.

Par exemple, on peut sélectionner les colonnes "nom_famille", "prenom" et "genre" :

table_deputes %>%
  select(nom_famille, prenom, genre)

On peut aussi utiliser des fonctions pour sélectionner rapidement plusieurs colonnes.

  • La fonction starts_with() sélectionne toutes les colonnes dont les noms commencent par une chaîne de caractères donnée.
  • La fonction ends_with() sélectionne toutes les colonnes dont les noms se terminent par une chaîne de caractères donnée.
  • La fonction contains() sélectionne toutes les colonnes dont les noms comprennent une chaîne de caractère donnée.
> table_deputes %>%
+   select(starts_with("nom")) %>%
+   head(n = 2)
# A tibble: 2 × 2
               nom nom_famille
             <chr>       <chr>
1  François Fillon      Fillon
2 François de Rugy     de Rugy
>
> table_deputes %>%
+   select(ends_with("naissance")) %>%
+   head(n = 2)
# A tibble: 2 × 2
  date_naissance lieu_naissance
          <dttm>          <chr>
1     1954-03-04        Le Mans
2     1973-12-06         Nantes
>
> table_deputes %>%
+   select(contains("nom")) %>%
+   head(n = 2)
# A tibble: 2 × 3
               nom   prenom nom_famille
             <chr>    <chr>       <chr>
1  François Fillon François      Fillon
2 François de Rugy François     de Rugy

Renommer les variables[modifier | modifier le wikicode]

La fonction names() permet d'afficher les noms de variables.

> table_deputes %>% names()
 [1] "nom"             "genre"           "prenom"          "nom_famille"     "date_naissance"
 [6] "lieu_naissance"  "circonscription" "sycomore_id"     "wikidata"        "frwiki"

La fonction rename() permet de renommer certaines variables d'un tableau de données. Par exemple, on peut renommer la variable frwiki en frwikipedia.

> table_deputes %>%
+   rename(frwikipedia = frwiki)  %>%
+   names()
 [1] "nom"             "genre"           "prenom"          "nom_famille"     "date_naissance"
 [6] "lieu_naissance"  "circonscription" "sycomore_id"     "wikidata"        "frwikipedia"

Trier le tableau de données[modifier | modifier le wikicode]

La fonction arrange() permet de trier le tableau de données en fonction des valeurs d'une ou plusieurs variables. Par exemple, on peut trier le jeu de données des députés en fonction de la date de naissance des députés :

> table_deputes %>%
+   arrange(date_naissance) %>%
+   head()
# A tibble: 6 × 10
                  nom    genre      prenom  nom_famille date_naissance lieu_naissance
                <chr>    <chr>       <chr>        <chr>         <dttm>          <chr>
1   François Scellier masculin    François     Scellier     1936-05-07         Amiens
2 Alfred Marie-Jeanne masculin      Alfred Marie-Jeanne     1936-11-15 Rivière-Pilote
3     Lucien Degauchy masculin      Lucien     Degauchy     1937-06-11  Hautefontaine
4    Bernard Brochand masculin     Bernard     Brochand     1938-06-05           Nice
5  Jean-Claude Mathis masculin Jean-Claude       Mathis     1939-08-15    Bouzonville
6   Jean-Michel Couve masculin Jean-Michel        Couve     1940-01-03         Le Muy
# ... with 4 more variables: circonscription <chr>, sycomore_id <int>, wikidata <chr>, frwiki <chr>

Par défaut, la fonction arrange() trie les valeurs par ordre ascendant. Pour trier les valeurs par ordre descendant, on peut combiner avec la fonction desc().

> table_deputes %>%
+   arrange(desc(date_naissance)) %>%
+   head()
# A tibble: 6 × 10
                     nom    genre  prenom     nom_famille date_naissance        lieu_naissance
                   <chr>    <chr>   <chr>           <chr>         <dttm>                 <chr>
1 Marion Maréchal-Le Pen  féminin  Marion Maréchal-Le Pen     1989-12-10 Saint-Germain-en-Laye
2         Marine Brenier  féminin  Marine         Brenier     1986-08-11                  Nice
3            Julien Dive masculin  Julien            Dive     1985-05-21         Saint-Quentin
4          Marie Le Vern  féminin   Marie         Le Vern     1983-01-11        Bois-Guillaume
5     Laurent Marcangeli masculin Laurent      Marcangeli     1980-12-10               Ajaccio
6   Fanélie Carrey-Conte  féminin Fanélie    Carrey-Conte     1980-05-16                Bègles
# ... with 4 more variables: circonscription <chr>, sycomore_id <int>, wikidata <chr>, frwiki <chr>

Définir de nouvelles variables[modifier | modifier le wikicode]

La fonction mutate() permet de définir de nouvelles variables.

Par exemple, sur la table des députés, on a la date de naissance. On peut calculer donc calculer l'âge des députés. Pour calculer l'âge, on utilise plusieurs fonction de la librairie lubridate. La fonction today() donne la date d'aujourd'hui. La fonction interval() permet de définir un intervalle de temps entre deux dates. Enfin, la fonction time_length() permet de convertir un intervalle de temps en un nombre dans une unité donnée. Ici, on choisit d'exprimer l'âge en année. Dans l'exemple, on combine aussi avec les fonctions select() et glimpse() pour afficher un aperçu du nouveau jeu de données avec la nouvelle variable.

> library(lubridate)
> table_deputes %>% 
+   mutate(
+     age = time_length(
+       interval(
+         start = date_naissance, 
+         end = today()
+         ), 
+       unit = "year"
+       )
+     ) %>%
+   select(nom, date_naissance, age) %>% 
+   glimpse()
Observations: 575
Variables: 3
$ nom            <chr> "François Fillon", "François de Rugy", "Hervé Gaymard", "Aurélie Filippetti", "De...
$ date_naissance <dttm> 1954-03-04, 1973-12-06, 1960-05-31, 1973-06-17, 1973-03-23, 1989-12-10, 1943-02-...
$ age            <dbl> 62.74247, 42.98361, 56.50137, 43.45479, 43.69041, 26.97268, 73.76503, 54.01370, 7..

Synthétiser un tableau de données[modifier | modifier le wikicode]

La fonction summarise() permet de synthétiser un jeu de données.

On peut par exemple reprendre l'exemple précédent et calculer l'âge moyen des députés. Pour cela, il suffit de définir la variable age = mean(age) dans la fonction summarise().

> table_deputes %>% 
+   mutate(
+     age = time_length(
+       interval(
+         start = date_naissance, 
+         end = today()
+         ), 
+       unit = "year"
+       )
+     ) %>%
+   summarise(age = mean(age))
# A tibble: 1 × 1
       age
     <dbl>
1 58.80746

On peut aussi calculer d'autres indicateurs comme l'écart-type, le minimum et le maximum :

> table_deputes %>% 
+   mutate(
+     age = time_length(
+       interval(
+         start = date_naissance, 
+         end = today()
+         ), 
+       unit = "year"
+       )
+     ) %>%
+   summarise(
+     age_moyen = mean(age), 
+     age_median = median(age), 
+     ecarttype_age = sd(age), 
+     min_age = min(age), 
+     max_age = max(age)
+     )
# A tibble: 1 × 5
  age_moyen age_median ecarttype_age  min_age  max_age
      <dbl>      <dbl>         <dbl>    <dbl>    <dbl>
1  58.80746   59.48219      10.10712 26.97268 80.56712

Comprendre les opérations par sous-groupe[modifier | modifier le wikicode]

La librairie dplyr permet de définir des opérations sur des sous-groupes.

La fonction group_by() permet de définir les sous-groupes et la fonction ungroup() de revenir à un tableau de données non groupé.

La fonction group_by() peut être combiné avec mutate() et summarise().


Voir aussi[modifier | modifier le wikicode]

Notes et références[modifier | modifier le wikicode]

  1. http://r4ds.had.co.nz/tibbles.html#tibbles-vs.data.frame
  2. http://vita.had.co.nz/papers/tidy-data.html
  3. http://www.data.gouv.fr/fr/datasets/listes-de-personnalites-issues-de-wikidata-1/