La philosophie de ce deuxième module diffère sensiblement de celle des modules 1 et 3. Son objectif est de vous amener à manipuler les briques élémentaires du langage de R : vecteurs, matrices et listes. À ce titre, il s’agit d’un détour indispensable avant d’aborder les opérations plus complexes portant sur les tables de données (sélection d’observations et de variables, tri, fusion, etc.).

Plus encore que les autres modules, il est pensé pour articuler étroitement apprentissage d’un “vocabulaire” de fonctions et mise en oeuvre autour de cas pratiques.

 

Les vecteurs : création et sélection

Les vecteurs constituent un des types d’objets les plus simples et les plus courants dans R. Ils interviennent dans la manipulation de la plupart des autres types d’objets et méritent à ce titre une attention particulière.

Exemples Les variables d’une table sont des vecteurs, tout comme la plupart des paramètres passés à une fonction.

Créer des vecteurs et connaître leurs caractéristiques

La fonction c() permet de créer des vecteurs :

# Création de vecteurs
c(8, 5)
  ## [1] 8 5
c("z","B","e")
  ## [1] "z" "B" "e"
c(TRUE, FALSE, FALSE, TRUE)
  ## [1]  TRUE FALSE FALSE  TRUE

Pour associer un vecteur à un nom d’objet, il suffit d’utiliser l’opérateur d’assignation <- :

# Assignation de vecteurs à des noms
a1 <- c(8, 5)
a2 <- c("z", "B", "e")
a3 <- c(TRUE, FALSE, FALSE, TRUE)

# Rappel de la valeur des vecteurs définis
a1
  ## [1] 8 5
a2
  ## [1] "z" "B" "e"
a3
  ## [1]  TRUE FALSE FALSE  TRUE

Un vecteur possède plusieurs caractéristiques essentielles (que l’on qualifie d’attributs) :

  • son type : les types les plus courants sont numérique, caractère et logique ;
  • sa longueur : le nombre d’éléments qui le composent.

Il est possible d’afficher ces attributs avec les fonctions str(), mode() et length().

# Attributs de a1
str(a1)
  ##  num [1:2] 8 5
mode(a1)
  ## [1] "numeric"
length(a1)
  ## [1] 2

# Attributs de a2
str(a2)
  ##  chr [1:3] "z" "B" "e"
mode(a2)
  ## [1] "character"
length(a2)
  ## [1] 3

# Attributs de a3
str(a3)
  ##  logi [1:4] TRUE FALSE FALSE TRUE
mode(a3)
  ## [1] "logical"
length(a3)
  ## [1] 4

Les fonctions is.numeric(), is.character() et is.logical() permettent de tester si un vecteur est de type numérique, caractère ou logique respectivement.

# Utilisation de is.numeric()
is.numeric(a1)
  ## [1] TRUE
is.numeric(a2)
  ## [1] FALSE
is.numeric(a3)
  ## [1] FALSE

# Utilisation de is.character()
is.character(a1)
  ## [1] FALSE
is.character(a2)
  ## [1] TRUE
is.character(a3)
  ## [1] FALSE

# Utilisation de is.logical()
is.logical(a1)
  ## [1] FALSE
is.logical(a2)
  ## [1] FALSE
is.logical(a3)
  ## [1] TRUE

 


Remarques :

  • Quand on souhaite créer un vecteur de longueur 1, la fonction c() est inutile. C’est ce qui a été fait pendant tout le module 1 de la formation.
# Création d'un vecteur de longueur 1
a4 <- 2
a5 <- c(2)
identical(a4, a5)
  ## [1] TRUE
  • Les vecteurs de type logique ne peuvent prendre que deux valeurs (en plus des valeurs manquantes NA, cf. infra) : vrai (TRUE) et faux (FALSE). TRUE et FALSE sont des mots-clés spécifiques qui doivent être écrits intégralement en majuscules :
# Création d'un vecteur logique
a6 <- c(TRUE, FALSE, TRUE, TRUE)
a6
  ## [1]  TRUE FALSE  TRUE  TRUE
is.logical(a6)
  ## [1] TRUE

# Quand TRUE et FALSE ne sont pas écrits intégralement 
# en majuscules, des erreurs surviennent
a7 <- c(True, fALSE, true,false)
  ## Error in eval(expr, envir, enclos): objet 'True' introuvable
# R recherche un objet dont le nom est `True` mais n'en 
# trouve aucun.
  • Quand nombres, caractères ou valeurs logiques coexistent dans la définition d’un vecteur, des conversions automatiques sont opérées :
# Création d'un vecteur mélangeant nombres, caractères
# et valeurs logiques
a8 <- c("a", 2, "b", TRUE)
a8
  ## [1] "a"    "2"    "b"    "TRUE"

# Des guillemets apparaissent autour des valeurs numériques
# ou logiques : le vecteur est de type caractère
is.character(a8)
  ## [1] TRUE

 

La fonction c() permet également de créer un vecteur à partir de plusieurs autres.

# Création des vecteurs de type caractère a9 et a10
a9 <- c("a", "b", "c", "d")
a10 <- c("mais", "ou", "et", "donc", "or", "ni", "car")

# Concaténation avec la fonction c()
c(a9, a10)
  ##  [1] "a"    "b"    "c"    "d"    "mais" "ou"   "et"   "donc" "or"   "ni"  
  ## [11] "car"
c(a10, a9)
  ##  [1] "mais" "ou"   "et"   "donc" "or"   "ni"   "car"  "a"    "b"    "c"   
  ## [11] "d"

La fonction rep() permet enfin de créer des vecteurs en répétant une ou plusieurs valeurs un certain nombre de fois.

# Création d'un vecteur avec la fonction rep()
rep(1, times = 5)
  ## [1] 1 1 1 1 1

# Quand le premier argument de rep() est un vecteur, 
# il est répété en entier
rep(c(1, 2), times = 5)
  ##  [1] 1 2 1 2 1 2 1 2 1 2

# Utilisé à la place de times = , l'argument each = 
# permet de répéter chaque élément et non le vecteur
# en entier
rep(c(1, 2), each = 5)
  ##  [1] 1 1 1 1 1 2 2 2 2 2

 

Cas pratique 2.1 Créer des vecteurs et connaître leurs caractéristiques

  1. Devinez le type et la longueur des vecteurs définis par le code suivant, puis vérifiez-les en créant ces vecteurs et en utilisant les fonctions str(), length() et mode().

    b1 <- c(1, 2, 3)
    b2 <- rep(c("aaa","bbb"), times = 2)
    b3 <- c(TRUE, FALSE, TRUE)
    b4 <- c("TRUE", "FALSE", "FALSE")
    b5 <- c(b2, b4)
    b6 <- c(b1, b3)

     

  2. Utilisez la fonction rep() pour créer la séquence 1, 2, 1, 2. Utilisez de nouveau rep() pour créer la séquence 1, 1, 1, 2, 2, 2. Combinez ces éléments pour créer la séquence 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2.

     

Extraire les éléments d’un vecteur

L’opérateur d’extraction [ permet de sélectionner des éléments en utilisant leur position dans le vecteur :

# Définition du vecteur c1
c1 <- c("a", "b", "c", "d", "e", "f", "g", "h", "i", "j")
c1
  ##  [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"

# Sélection de l'élément en position 2
c1[2]
  ## [1] "b"

# Sélection de l'élément en position 5
c1[5]
  ## [1] "e"

Pour extraire plus d’une valeur à la fois, il suffit d’utiliser l’opérateur [ avec le vecteur des positions souhaitées :

# Sélection des éléments en position 3 et 6
c1[c(3, 6)]
  ## [1] "c" "f"

Pour sélectionner toutes les valeurs sauf certaines, il suffit de d’indiquer leur position précédée de - :

# Sélection de tous les éléments SAUF celui en position 3
c1[-3]
  ## [1] "a" "b" "d" "e" "f" "g" "h" "i" "j"

# Sélection de tous les éléments SAUF ceux en position 2 et 7
c1[-c(2,7)]
  ## [1] "a" "c" "d" "e" "f" "h" "i" "j"

 

Il est également possible de définir des vecteurs dont chaque élément est nommé :

# Création du vecteur numérique c2 nommé
c2 <- c("pierre" = 1, "feuille" = 2, "ciseaux" = 3)
c2
  ##  pierre feuille ciseaux 
  ##       1       2       3

Il est alors possible d’utiliser les noms pour sélectionner un ou plusieurs éléments :

# Sélection de l'élément associé au nom "pierre"
c2["pierre"]
  ## pierre 
  ##      1

# Sélection des éléments associés aux noms "ciseaux" et "feuille"
c2[c("ciseaux","feuille")]
  ## ciseaux feuille 
  ##       3       2

Il est possible d’afficher et de modifier les noms associés à un vecteur en utilisant la fonction names() :

# Affichage des noms associés au vecteur c2
names(c2)
  ## [1] "pierre"  "feuille" "ciseaux"

# Modification des noms associés au vecteur c2
names(c2) <- c("rouge", "jaune", "bleu")
c2
  ## rouge jaune  bleu 
  ##     1     2     3

 


Remarque importante Les éléments d’un vecteur sont extraits dans l’ordre dans lequel sont renseignés les positions ou les noms.

# On compare le résultat de c1[c(3, 6)] et de c1[c(6, 3)]
c1
  ##  [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"

c1[c(3, 6)]
  ## [1] "c" "f"

c1[c(6, 3)]
  ## [1] "f" "c"

# Cela est vrai également quand l'extraction est opérée par les noms
c2
  ## rouge jaune  bleu 
  ##     1     2     3

c2[c("rouge", "jaune")]
  ## rouge jaune 
  ##     1     2

c2[c("jaune", "rouge")]
  ## jaune rouge 
  ##     2     1

En cas de répétition d’une position ou d’un nom, l’élément du vecteur correspondant est répété dans le résultat :

c1[c(3, 3, 6, 6)]
  ## [1] "c" "c" "f" "f"

c2[c("rouge", "jaune", "jaune", "rouge")]
  ## rouge jaune jaune rouge 
  ##     1     2     2     1

Cette propriété est extrêmement importante, dans la mesure où c’est sur elle que repose les opérations de tri de tables de données via la fonction order() (cf. infra et module 3).


 

 

Cas pratique 2.2 Extraire les valeurs d’un vecteur

  1. On définit le vecteur numérique d1 par d1 <- c(2, 7, 5, 8). Sélectionnez l’élément en troisième position, puis les éléments en quatrième et deuxième positions (dans cet ordre). Sélectionnez enfin tous les éléments sauf celui en première position.

     

  2. On définit le vecteur logique d2 nommé par d2 <- c("a" = TRUE, "b" = FALSE, "c" = FALSE, "d" = TRUE, "e" = TRUE). Que signifient les lettres "a", "b", "c", "d" et "e" dans la définition du vecteur ? Proposez deux méthodes pour sélectionner les éléments de d2 situé en troisième et première position (dans cet ordre).

     

  3. Affichez le vecteur de noms associé au vecteur d2 avec la fonction names(). Quel est le type de ce vecteur ? Modifiez le vecteur de noms associé au vecteur d2 et remplacez le par c(2011, 2012, 2013, 2014, 2015).

     

  4. (Optionnel) Que se passe-t-il quand vous saisissez d2[c(2012, 2015)]. Comment le comprenez-vous ? Quel code proposeriez-vous pour sélectionner les éléments dont les noms sont "2012" et "2015" ?

     

     

 

Les vecteurs : types et opérations

Manipuler des vecteurs logiques

Les vecteurs logiques sont particulièrement importants dans la mesure où ils interviennent dans l’évaluation et l’utilisation d’expressions logiques. Comme la plupart des langages, R dispose d’opérateurs logiques lui permettant d’évaluer certaines expressions (cf. tableau). Ces opérateurs ne sont rien d’autres que des fonctions dont le résultat est un vecteur logique.

Code R Résultat
a == 1 Renvoie TRUE si a vaut 1
a != 1 Renvoie TRUE si a est différent de 1
a < 1 Renvoie TRUE si a est strictement inférieur à 1
a <= 1 Renvoie TRUE si a est inférieur ou égal à 1
a > 1 Renvoie TRUE si a est strictement supérieur à 1
a >= 1 Renvoie TRUE si a est supérieur ou égal à 1
a & b Renvoie TRUE si a est TRUE et b est TRUE
a | b Renvoie TRUE si a est TRUE ou b est TRUE
!a Renvoie TRUE si a est FALSE, FALSE si a est TRUE
a %in% c(1,2) Renvoie TRUE si a vaut 1 ou 2
# Définition du vecteur e1
e1 <- c(1, 2, 3, 4, 5)
e1
  ## [1] 1 2 3 4 5

# Evaluation d'expressions logiques
e1 == 3
  ## [1] FALSE FALSE  TRUE FALSE FALSE

e1 != 3
  ## [1]  TRUE  TRUE FALSE  TRUE  TRUE

e1 < 3
  ## [1]  TRUE  TRUE FALSE FALSE FALSE

e1 <= 3
  ## [1]  TRUE  TRUE  TRUE FALSE FALSE

!(e1 <= 3)
  ## [1] FALSE FALSE FALSE  TRUE  TRUE

e1 >= 1 & e1 < 4
  ## [1]  TRUE  TRUE  TRUE FALSE FALSE

e1 < 2 | e1 > 4
  ## [1]  TRUE FALSE FALSE FALSE  TRUE

e1 %in% c(1, 3)
  ## [1]  TRUE FALSE  TRUE FALSE FALSE

 

Les vecteurs logiques peuvent ainsi être utilisés dans de nombreuses situations :

  • combinés avec la fonction sum(), pour déterminer le nombre d’éléments d’un vecteur qui respectent une certaine condition :

    e1
      ## [1] 1 2 3 4 5
    # Nombre d'éléments de e1 strictement inférieurs à 3
    sum(e1 < 3)
      ## [1] 2
  • combinés avec la fonction which(), pour récupérer la position des éléments d’un vecteur respectant une certaine condition :

    e1
      ## [1] 1 2 3 4 5
    # Position des éléments de e1 strictement supérieurs à 2
    which(e1 > 2)
      ## [1] 3 4 5
  • combinés avec l’opérateur d’extraction [, pour sélectionner ou remplacer les éléments respectant une certaine condition :

    e1
      ## [1] 1 2 3 4 5
    # Sélection des éléments de e1 dont la valeur 
    # est strictement inférieure à 3
    e1[e1 < 3]
      ## [1] 1 2
    
    # Remplacement des éléments de e1 dont la valeur 
    # est strictement inférieure à 3 par 0
    e1[e1 < 3] <- 0
    e1
      ## [1] 0 0 3 4 5

 


À retenir Il existe ainsi trois méthodes pour extraire les éléments d’un vecteur via l’opérateur [ :

  • utiliser un vecteur de positions;
  • utiliser un vecteur de noms (quand des noms sont définis);
  • utiliser un vecteur logique de même longueur.
e2 <- c("a" = 1, "b" = 2, "c" = 3, "d" = 4, "e" = 5)
e2
  ## a b c d e 
  ## 1 2 3 4 5
# Objectif : extraire les éléments en 2ème et 5ème position de e2

# Méthode 1 : par les positions
e2[c(2, 5)]
  ## b e 
  ## 2 5

# Méthode 2 : par les noms
e2[c("b", "e")]
  ## b e 
  ## 2 5

# Méthode 3 : avec un vecteur logique de longueur 5
# (car e2 est de longueur 5)
e2[c(FALSE, TRUE, FALSE, FALSE, TRUE)]
  ## b e 
  ## 2 5

Les deux premières méthodes permettent de modifier l’ordre des éléments ou de les répéter, mais pas la troisième :

e2
  ## a b c d e 
  ## 1 2 3 4 5

e2[c(2, 1, 2, 3, 1)]
  ## b a b c a 
  ## 2 1 2 3 1

e2[c("b", "a", "b", "c", "a")]
  ## b a b c a 
  ## 2 1 2 3 1

e2[c(TRUE, TRUE, TRUE, FALSE, FALSE)]
  ## a b c 
  ## 1 2 3
# Note : il est impossible de changer l'ordre dans lequel apparaissent
# les éléments extraits (ni de les répéter) quand on utilise un vecteur
# logique pour mener l'extraction.

L’utilisation de vecteurs logique pour extraire des valeurs est particulièrement importante, dans la mesure où elle intervient dans la plupart des opérations de sélection d’observations ou de variables dans une table de données (cf. infra et module 3).


 

 

Cas pratique 2.3 Manipuler des vecteurs logiques

  1. On définit le vecteur f1 <- c(5, 2, -4, 8). Devinez la valeur que renvoient les expressions logiques suivantes, puis vérifiez-les en créant f1 et en les évaluant.

    f1 == 2
    f1 != 7
    f1 < 6
    f1 != 2
    !(f1  == 2)
    f1 > 3 & f1 != 5
    (f1 < 1 | f1 > 3) & f1 != 8
    f1 %in% c(-4, 7)

     

  2. On définit le vecteur f2 <- rep(c("a","b","a"), times = 10). Déterminez automatiquement le nombre d’éléments de f2 égaux à "a" ainsi que leur position. Sélectionnez les éléments égaux à "b" et remplacez leur valeur par "c".

     

Manipuler des vecteurs numériques

Plusieurs fonctions sont spécifiquement utilisées pour générer des vecteurs de type numérique :

  • seq() : seq() produit des séquences de nombres. Dans les cas courants, elle peut être remplacée par : :

    # Création d'un vecteur avec la fonction seq()
    seq(1, 20)
      ##  [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20
    
    # Remplacement par `:`
    1:20
      ##  [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20
    
    # Un cas particulier où seq() ne peut pas directement être remplacé
    # par `:`
    seq(1, 20, by = 2)
      ##  [1]  1  3  5  7  9 11 13 15 17 19
  • les fonctions rXXXX de tirage dans une variable (pseudo-)aléatoire : R dispose d’un large famille de fonctions tirant de façon pseudo-aléatoire selon une certaine loi (spécifiée par les lettres XXXX). Les plus fréquemment utilisées sont runif() (loi uniforme sur [0;1]) et rnorm() (loi normale centrée réduite) :

    # Création d'un vecteur de taille 20 avec la fonction runif()
    runif(20)
      ##  [1] 0.26550866 0.37212390 0.57285336 0.90820779 0.20168193 0.89838968
      ##  [7] 0.94467527 0.66079779 0.62911404 0.06178627 0.20597457 0.17655675
      ## [13] 0.68702285 0.38410372 0.76984142 0.49769924 0.71761851 0.99190609
      ## [19] 0.38003518 0.77744522
    
    # Création d'un vecteur de taille 20 avec la fonction rnorm()
    rnorm(20)
      ##  [1]  1.51178117  0.38984324 -0.62124058 -2.21469989  1.12493092
      ##  [6] -0.04493361 -0.01619026  0.94383621  0.82122120  0.59390132
      ## [11]  0.91897737  0.78213630  0.07456498 -1.98935170  0.61982575
      ## [16] -0.05612874 -0.15579551 -1.47075238 -0.47815006  0.41794156

 

Les opérations arithmétiques sont appliquées termes à termes sur des vecteurs :

# Génération de deux vecteurs numériques
g1 <- rep(2, times = 10)
g1
  ##  [1] 2 2 2 2 2 2 2 2 2 2
g2 <- 1:10
g2
  ##  [1]  1  2  3  4  5  6  7  8  9 10

# Application d'opérateurs arithmériques
g1 + g2
  ##  [1]  3  4  5  6  7  8  9 10 11 12
g1 - g2
  ##  [1]  1  0 -1 -2 -3 -4 -5 -6 -7 -8
g1 * g2
  ##  [1]  2  4  6  8 10 12 14 16 18 20
g1 / g2
  ##  [1] 2.0000000 1.0000000 0.6666667 0.5000000 0.4000000 0.3333333 0.2857143
  ##  [8] 0.2500000 0.2222222 0.2000000

Quand les vecteurs ne sont pas de même longueur, les éléments du plus petit des deux sont automatiquement répétés. Un avertissement apparaît quand la longueur du plus grand vecteur n’est pas un multiple de la longueur du plus petit.

g1
  ##  [1] 2 2 2 2 2 2 2 2 2 2

# Répétition automatique des éléments du vecteur g3
g3 <- 1:5
g3
  ## [1] 1 2 3 4 5
g1 + g3
  ##  [1] 3 4 5 6 7 3 4 5 6 7

# Répétition automatique des éléments du vecteur g4
g4 <- 1:3
g4
  ## [1] 1 2 3
g1 + g4
  ## Warning in g1 + g4: la taille d'un objet plus long n'est pas multiple de la
  ## taille d'un objet plus court
  ##  [1] 3 4 5 3 4 5 3 4 5 3

Cette réutilisation des éléments du vecteur permet de très simplement effectuer des opérations entre un vecteur de taille quelconque et un scalaire (i.e. un vecteur de taille 1).

# Opération entre un vecteur et un scalaire
g2 * 3
  ##  [1]  3  6  9 12 15 18 21 24 27 30
# La valeur unique du vecteur c(3) est réutilisée
# pour atteindre la longueur de g2 (10). 

 

Enfin, de nombreuses fonctions peuvent être appliquées à l’ensemble d’un vecteur de type numérique (cf. tableau).

Code R Résultat
sum(v) Somme du vecteur v
cumsum(v) Somme cumulée du vecteur v
mean(v) Moyenne du vecteur v
quantile(v) Quantiles du vecteur v
summary(v) Moyenne et quantiles du vecteur v
max(v) Valeur maximum du vecteur v
min(v) Valeur minimum du vecteur v
which.min(v) Position du minimum du vecteur v
which.max(v) Position du maximum du vecteur v
round(v, 2) Arrondi du vecteur v à deux décimales

 

Cas pratique 2.4 Manipuler des vecteurs numériques

  1. Utilisez la fonction seq() pour construire la série de nombres de 0 à 10 de 0.5 en 0.5. Comment pourriez-vous y parvenir en utilisant l’opérateur : ?

     

  2. Générez un vecteur h1 de longueur 20 tiré dans une loi uniforme sur [0;1]. Sélectionnez les éléments de h1 dont la position est paire selon deux méthodes, l’une utilisant la fonction seq() et l’autre la fonction rep().

     

  3. En vous inspirant de la méthode utilisant la fonction seq() de la question précédente, construisez la fonction elementsPairs(x) qui retourne automatiquement les éléments du vecteur x dont la position est paire.

     

     

  4. Créez un vecteur h2 de longueur 15 et tiré dans une loi normale centrée réduite. Déterminez sa valeur maximale. En utilisant notamment l’opérateur d’extraction [, déterminez alors la deuxième valeur maximale de h2.

     

Manipuler des vecteurs caractères

Comme pour les vecteurs de type numérique, il existe dans R des fonctions spécifiquement adaptées pour créer et manipuler des vecteurs de type caractère :

  • nchar(), toupper(), tolower() : nchar() renvoie le nombre de caractères que représente chaque élément d’un vecteur de type caractère, les fonctions tolower() et toupper() convertissent un vecteur caractère en minuscules et majuscules respectivement.

    # Création du vecteur i1
    i1 <- c("aa", "B", "cccc", "DDD")
    i1
      ## [1] "aa"   "B"    "cccc" "DDD"
    
    # Détermination du nombre de caractères avec nchar()
    nchar(i1)
      ## [1] 2 1 4 3
    
    # Passage en minuscules ou en majuscules
    tolower(i1)
      ## [1] "aa"   "b"    "cccc" "ddd"
    toupper(i1)
      ## [1] "AA"   "B"    "CCCC" "DDD"

 

  • paste(): paste() et sa variante paste0() permettent d’agglutiner un ou plusieurs vecteurs caractères.

    # Création des vecteurs i2 et i3
    i2 <- c("a", "b")
    i3 <- c("c", "d")
    
    # Fonctionnement de paste() et paste0()
    paste(i2, i3)
      ## [1] "a c" "b d"
    paste(i2, i3, sep = "_")
      ## [1] "a_c" "b_d"
    paste0(i2, i3)
      ## [1] "ac" "bd"
    
    # Argument collapse = 
    paste(i2, collapse = "*")
      ## [1] "a*b"
    paste(i2, i3, sep = "_", collapse = "*")
      ## [1] "a_c*b_d"

 

  • formatC: formatC() convertit un vecteur numérique en vecteur caractère en spécifiant un format.

    # Utilisation de formatC() pour ajouter des zéros
    # devant des chiffres 
    formatC(c(1, 2, 56, 789), flag = "0", width = 4)
      ## [1] "0001" "0002" "0056" "0789"

 

  • letters et LETTERS: letters et LETTERS sont des objets qui contiennent les 26 lettres de l’alphabet, en minuscules et en majuscules respectivement.

    letters
      ##  [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q"
      ## [18] "r" "s" "t" "u" "v" "w" "x" "y" "z"
    LETTERS
      ##  [1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q"
      ## [18] "R" "S" "T" "U" "V" "W" "X" "Y" "Z"

 

Cas pratique 2.5 Manipuler des vecteurs caractères : Reconstituer un identifiant de fiche-adresse

L’objectif de ce cas pratique est de reconstituer un identifiant de fiche-adresse (utilisé dans les enquêtes auprès des ménages de l’Insee) à partir de trois informations :

  • le numéro de la région de gestion (rges) codé sur deux positions ;
  • le numéro de la fiche-adresse (numfa) codé sur six positions (avec des 0 devant si nécessaire) ;
  • le numéro de sous-échantillon (ssech) codé sur deux positions (avec un 0 devant si nécessaire).
rges <- c(11, 11, 21, 21, 22, 31, 74, 81, 81, 94)
numfa <- c(1, 102, 32, 1219, 98, 3, 678, 21, 89, 45)
ssech <- c(1, 11, 1, 1, 1, 2, 2, 2, 12, 11)

L’identifiant de fiche-adresse est défini par la concaténation de rges, numfa et ssech: rges||numfa||ssech. Par exemple, si rges = 11, numfa = 1 et ssech = 1, l’identifiant de fiche-adresse est 1100000101 (après ajout de 0 intercalaires).

  1. Utilisez la fonction paste() pour agglutiner les vecteurs rges, numfa et ssech. Utilisez l’argument sep = pour supprimer le séparateur. Cela produit-il le résultat souhaité ?

     

  2. Utilisez la fonction formatC() pour reformater correctement le vecteur numfa. Combinez les fonctions formatC() et paste() (ou paste0()) et appliquez-les à numfa et à ssech pour obtenir le résultat souhaité.

     

  3. Créez la fonction creerIdentFA(rges, numfa, ssech) qui produise automatiquement l’identifiant de fiche-adresse.

     

Modifier la structure d’un vecteur

Plusieurs fonctions sont susceptibles d’être appliquées à un vecteur pour modifier ses caractéristiques :

  • les opérations ensemblistes : fonctions intersect() et setdiff()

    # Création des vecteurs k1 et k2
    k1 <- letters[1:4]
    k2 <- letters[3:6]
    k1
      ## [1] "a" "b" "c" "d"
    k2
      ## [1] "c" "d" "e" "f"
    
    # Intersection de k1 et k2
    intersect(k1, k2)
      ## [1] "c" "d"
    
    # Elements présents dans k1 mais pas dans k2
    setdiff(k1, k2)
      ## [1] "a" "b"
    
    # Elements présents dans k2 mais pas dans k1
    setdiff(k2, k1)
      ## [1] "e" "f"

 

  • les fonctions de traitement des doublons : la fonction duplicated(x) indique si un élément est le doublon d’un élément dont la position est inférieure dans le vecteur x (autrement dit qui apparaît précédemment dans le vecteur), la fonction unique(x) renvoie le vecteur x sans doublons.

    # Création du vecteur k3
    k3 <- c(1, 2, 1, 4, 2, 3)
    k3
      ## [1] 1 2 1 4 2 3
    
    # Détection des éléments qui sont des doublons
    duplicated(k3)
      ## [1] FALSE FALSE  TRUE FALSE  TRUE FALSE
    
    # Suppression des doublons
    unique(k3)
      ## [1] 1 2 4 3

 

  • les fonctions de changement d’ordre : rev(x) inverse l’ordre du vecteur x, sort(x) renvoie le vecteur x trié et order(x) renvoie la permutation des positions du vecteur x nécessaire pour que x soit trié

    # Création du vecteur k4
    k4 <- c("a", "d", "b", "c")
    k4
      ## [1] "a" "d" "b" "c"
    
    # Inversion de k4
    rev(k4)
      ## [1] "c" "b" "d" "a"
    
    # Tri de k4 avec sort()
    sort(k4)
      ## [1] "a" "b" "c" "d"
    
    # Tri de k4 avec order()
    order(k4)
      ## [1] 1 3 4 2
    k4[order(k4)]
      ## [1] "a" "b" "c" "d"

    Remarque Le tri d’un vecteur avec order() est beaucoup moins intuitif qu’avec sort() et ne présente pas grand intérêt en lui-même. Néanmoins, seule la méthode avec order() est utilisable sur une table de données (cf. module 3), aussi autant se familiariser au plus tôt avec sa logique de fonctionnement !


 

Cas pratique 2.6 Modifier la structure d’un vecteur : Travailler avec des identifiants

L’objectif de ce cas pratique est d’utiliser les fonctions présentées dans cette sous-partie pour travailler efficacement avec des identifiants dans R. On définit les deux vecteurs suivants :

# Départements d'Ile-de-France présents dans une enquête
enq <- c("91", "75", "75", "94", "93", "94", "78", "77", "77")

# Liste des départements de la petite couronne
pc <- c("75", "92", "93", "94")
  1. À l’aide d’opérations ensemblistes, déterminez :

    1. les départements de la petite couronne présents dans l’enquête ;
    2. les départements de la petite couronne absents de l’enquête ;
    3. les départements de l’enquête qui ne sont pas dans la petite couronne.

     

  2. Le vecteur enq comporte-t-il des valeurs en double ? Répondez en utilisant la fonction duplicated(). Supprimez les valeurs en double dans enq avec duplicated() ou unique().

     

  3. Proposez deux méthodes pour trier le vecteur enq, une qui utilise sort() et une qui utilise order().

 

 

Les vecteurs : aspects particuliers

Savoir traiter les valeurs spéciales

R dispose de plusieurs valeurs spéciales qui interviennent dans des situations très différentes :

  • NA (pour Not Available) correspond à des valeurs manquantes. Il est très fréquent en pratique de rencontrer des valeurs NA dans des tableaux de données. À noter que les valeurs manquantes sont toujours indiquées par NA, quel que soit le type du vecteur.

    # Exemple de vecteurs présentant des valeurs NA
    l1 <- c(1, 2, 3, NA, 5)
    l1
      ## [1]  1  2  3 NA  5
    l2 <- c("a", "b", NA, "d")
    l2
      ## [1] "a" "b" NA  "d"
    l3 <- c(NA, NA, TRUE, FALSE)
    l3
      ## [1]    NA    NA  TRUE FALSE

 

  • Inf et -Inf correspondent à l’infini en positif et en négatif respectivement.

    # Exemple de situation dans laquelle survient un Inf
    5/0
      ## [1] Inf

 

  • NaN (pour Not a Number) correspond aux cas dans lesquels un calcul mathématique ne conduit à aucun résultat sensé.

    # Exemple de situation dans laquelle survient un NaN
    0/0
      ## [1] NaN

 

Pour identifier (voire supprimer ou remplacer) ces valeurs spéciales, des fonctions spécifiques existent : is.na(), is.infinite(), is.nan().

# Création du vecteur l4
l4 <- c(1, NA, 3, NaN, 5, Inf)
l4
  ## [1]   1  NA   3 NaN   5 Inf

is.na(l4)
  ## [1] FALSE  TRUE FALSE  TRUE FALSE FALSE
# Remarque : la fonction is.na() identifie à la fois les éléments NA
# et les éléments NaN. 

is.nan(l4)
  ## [1] FALSE FALSE FALSE  TRUE FALSE FALSE
# Remarque : la fonction is.nan() n'identifie que les éléments NaN
# (pas les éléments NA)

# Pour identifier les éléments NA uniquement (et pas les NaN), il suffit
# de combiner logiquement is.na() et is.nan()
is.na(l4) & !is.nan(l4)
  ## [1] FALSE  TRUE FALSE FALSE FALSE FALSE

is.infinite(l4)
  ## [1] FALSE FALSE FALSE FALSE FALSE  TRUE

 

Ces valeurs changent le comportement de la plupart des fonctions, notamment les fonctions sum(), table().

l1
  ## [1]  1  2  3 NA  5

# En présence d'une ou plusieurs valeurs NA, la fonction sum() 
# renvoie systématiquement NA
sum(l1)
  ## [1] NA

# Pour modifier ce comportement, il suffit d'utiliser l'argument 
# na.rm = TRUE de la fonction sum() (taper ? sum pour plus 
# d'informations).
sum(l1, na.rm = TRUE)
  ## [1] 11

# Par défaut, la fonction table() n'affiche pas les valeurs manquantes
l5 <- c("Femme", NA, "Homme", "Femme", NA, "Femme")
table(l5)
  ## l5
  ## Femme Homme 
  ##     3     1

# Utiliser l'argument useNA = "always" permet d'afficher
# toujours le nombre de valeurs NA (y compris quand il n'y
# en a 0).
table(l5, useNA = "always")
  ## l5
  ## Femme Homme  <NA> 
  ##     3     1     2

Remarque importante En présence d’une valeur NA, l’opérateur == renvoie NA. Ce comportement ne correspond pas à celui d’autres logiciels statistiques et peut s’avérer source d’erreur dans le recodage de variables. Pour cette raison, on peut lui préférer systématiquement l’opérateur %in%.

l5
  ## [1] "Femme" NA      "Homme" "Femme" NA      "Femme"

# En présence de valeurs NA, == renvoie NA
l5 == "Homme"
  ## [1] FALSE    NA  TRUE FALSE    NA FALSE

# En présence de valeurs NA, %in% renvoie FALSE
l5 %in% "Homme"
  ## [1] FALSE FALSE  TRUE FALSE FALSE FALSE

Conversion de type et type facteur

On a vu que quand c’est nécessaire, R modifie le type d’un vecteur pour s’adapter à de nouvelles données.

# Création du vecteur logique n1
n1 <- c(FALSE, TRUE, FALSE)

# Conversion en cas de concaténation avec un vecteur 
# de type numérique
c(n1, 3)
  ## [1] 0 1 0 3

# Conversion en cas de concaténation avec un vecteur 
# de type caractère
c(n1, "a")
  ## [1] "FALSE" "TRUE"  "FALSE" "a"

Mais il est aussi parfois très utile de convertir explicitement des vecteurs d’un type dans un autre, grâce aux fonctions as.numeric(), as.character() et as.logical().

# Âge codé en caractères
age <- c("56", "14", "78")
as.numeric(age)
  ## [1] 56 14 78

# Indicatrice codée en numérique
indic <- c(1, 0, 0, 1, 0)
as.logical(indic)
  ## [1]  TRUE FALSE FALSE  TRUE FALSE

Ces opérations peuvent néanmoins produire des NA, en particulier quand un vecteur caractère est converti en vecteur numérique.

# Conversion du département en numérique
dep <- c("75", "92", "93", "13", "2A", "2B")
as.numeric(dep)
  ## Warning: NAs introduits lors de la conversion automatique
  ## [1] 75 92 93 13 NA NA

 

D’autre part, le type “facteur” est un type de vecteur particulier, à mi-chemin entre le vecteur caractère et le vecteur numérique :

  • les valeurs stockées par R sont des entiers ;
  • MAIS à chaque entier est associé un “label” permettant d’afficher une chaîne de caractère à la place du nombre correspondant.

Les objets de type facteur sont créés le plus souvent avec la fonction factor().

# Création du vecteur de type factor n2
n2 <- factor(c("banane", "pomme", "poire", "banane", "banane"))
n2
  ## [1] banane pomme  poire  banane banane
  ## Levels: banane poire pomme

# Caractéristiques de n2
str(n2)
  ##  Factor w/ 3 levels "banane","poire",..: 1 3 2 1 1

La fonction str() révèle que les valeurs stockées sont 1, 3, 2, 1, 1, valeurs qui sont “formatées”" par le biais des “labels” (levels) banane, poire, pomme.


Remarque On retrouve en fait exactement la même logique que le formatage de variable dans SAS ou l’utilisation de labels de variables dans Stata.


Quand une variable de type caractère comporte un nombre limité de modalités distinctes, le type facteur peut induire d’importants gains de performance : il est en effet plus efficace de stocker et de manipuler des nombres entiers que des chaînes de caractère parfois longues.

R étant un logiciel à l’origine pensé pour la statistique mathématique où les variables proprement caractère sont peu nombreuses, la plupart des fonctions de base proposent par défaut de convertir les variables de type caractère en variables de type facteur. C’est notamment le cas des fonctions d’importation standards (read.table(), read.dbf()) mais aussi de la fonction de construction des objets de type data.frame (cf. module 3).

 

Les matrices : création et sélection

Les matrices peuvent être vues comme le prolongement en deux dimensions des vecteurs : si ce n’est l’existence de deux jeux de positions au lieu d’un seul et de quelques fonctions spécifiques, leurs principes d’utilisation sont les mêmes.

Le type d’objet utilisé pour stocker des données statistiques, le data.frame (cf. module 3) présente des points communs avec les matrices (accès aux objets par deux positions, utilisation de fonctions adaptées aux objets en deux dimensions, etc.).

La fonction matrix() est la manière la plus simple de créer des matrices.

matrix(1:8, nrow = 2, ncol = 4)
  ##      [,1] [,2] [,3] [,4]
  ## [1,]    1    3    5    7
  ## [2,]    2    4    6    8

R utilise les valeurs du premier argument (un vecteur de données) pour remplir la matrice dont les dimensions sont indiquées par les arguments nrow (nombre de lignes) et ncol (nombre de colonnes).

Par défaut, R remplit la matrice colonne par colonne : d’abord la première colonne de haut en bas, puis la deuxième de haut en bas, etc. L’argument byrow (FALSE par défaut) permet de remplir la matrice ligne par ligne.

matrix(1:8, nrow = 2, ncol = 4, byrow = TRUE)
  ##      [,1] [,2] [,3] [,4]
  ## [1,]    1    2    3    4
  ## [2,]    5    6    7    8

Comme un vecteur, une matrice a un type (fonction mode()). Sa longueur (fonction length()) correspond à la longueur de son vecteur de données. Ses dimensions sont accessibles via les fonctions dim(), nrow() et ncol().

# Création de la matrice o1
o1 <- matrix(letters[1:15], nrow = 3, ncol = 5)
o1
  ##      [,1] [,2] [,3] [,4] [,5]
  ## [1,] "a"  "d"  "g"  "j"  "m" 
  ## [2,] "b"  "e"  "h"  "k"  "n" 
  ## [3,] "c"  "f"  "i"  "l"  "o"

# Caractéristiques de o1
str(o1)
  ##  chr [1:3, 1:5] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" ...
mode(o1)
  ## [1] "character"
length(o1)
  ## [1] 15
dim(o1)
  ## [1] 3 5
nrow(o1)
  ## [1] 3
ncol(o1)
  ## [1] 5

On peut toujours à partir d’une matrice revenir au vecteur de données en utilisant les fonctions c() ou as.vector().

# Reconstitution du vecteur de données de 
# la matrice o1
c(o1)
  ##  [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o"
as.vector(o1)
  ##  [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o"

 

Pour sélectionner un élément dans une matrice, il suffit d’utiliser l’opérateur [ avec deux nombres correspondant à la position de l’élément séparés par une virgule :

o1
  ##      [,1] [,2] [,3] [,4] [,5]
  ## [1,] "a"  "d"  "g"  "j"  "m" 
  ## [2,] "b"  "e"  "h"  "k"  "n" 
  ## [3,] "c"  "f"  "i"  "l"  "o"

# Sélection de l'élément en ligne 2 et colonne 3
o1[2, 3]
  ## [1] "h"
# Note : Le premier nombre correspond à la ligne,
# le second à la colonne

Pour sélectionner une ligne ou une colonne entière, il suffit de n’indiquer qu’un seul nombre mais bien toujours la virgule ,.

o1
  ##      [,1] [,2] [,3] [,4] [,5]
  ## [1,] "a"  "d"  "g"  "j"  "m" 
  ## [2,] "b"  "e"  "h"  "k"  "n" 
  ## [3,] "c"  "f"  "i"  "l"  "o"

# Sélection de toute la première ligne
o1[1, ]
  ## [1] "a" "d" "g" "j" "m"

# Sélection de toute la cinquième colonne
o1[, 5]
  ## [1] "m" "n" "o"

Il est également possible de sélectionner les lignes et les colonnes d’une matrice par le biais de vecteurs logiques.

o1
  ##      [,1] [,2] [,3] [,4] [,5]
  ## [1,] "a"  "d"  "g"  "j"  "m" 
  ## [2,] "b"  "e"  "h"  "k"  "n" 
  ## [3,] "c"  "f"  "i"  "l"  "o"

# Sélection de toute la deuxième ligne
o1[c(FALSE, TRUE, FALSE), ]
  ## [1] "b" "e" "h" "k" "n"

# Sélection des colonnes 2 et 4
o1[, c(FALSE, TRUE, FALSE, TRUE, FALSE)]
  ##      [,1] [,2]
  ## [1,] "d"  "j" 
  ## [2,] "e"  "k" 
  ## [3,] "f"  "l"

 

Comme pour les vecteurs, il est également possible d’assigner des noms à une matrice à l’aide des fonctions rownames() et colnames(). Quand une matrice dispose de noms, ils peuvent être utilisés en lieu et place des positions de ligne et de colonne.

# Ajout de noms de lignes à o1
rownames(o1) <- c("pierre", "feuille", "ciseaux")
colnames(o1) <- c("pouce", "index", "majeur", "annulaire", "auriculaire")
o1
  ##         pouce index majeur annulaire auriculaire
  ## pierre  "a"   "d"   "g"    "j"       "m"        
  ## feuille "b"   "e"   "h"    "k"       "n"        
  ## ciseaux "c"   "f"   "i"    "l"       "o"

# Sélection d'éléments par le nom
o1["pierre", "index"]
  ## [1] "d"
o1["feuille", ]
  ##       pouce       index      majeur   annulaire auriculaire 
  ##         "b"         "e"         "h"         "k"         "n"
o1[, "annulaire"]
  ##  pierre feuille ciseaux 
  ##     "j"     "k"     "l"

 


À retenir Comme pour les vecteurs, il existe donc trois méthodes pour sélectionner des lignes ou des colonnes dans une matrice via l’opérateur [:

  • utiliser un vecteur de positions;
  • utiliser un vecteur de noms (quand des noms sont définis);
  • utiliser un vecteur logique.
o1
  ##         pouce index majeur annulaire auriculaire
  ## pierre  "a"   "d"   "g"    "j"       "m"        
  ## feuille "b"   "e"   "h"    "k"       "n"        
  ## ciseaux "c"   "f"   "i"    "l"       "o"

# On cherche à sélectionner la première et de la troisième ligne de o1

# Méthode 1 : par les positions
o1[c(1, 3), ]
  ##         pouce index majeur annulaire auriculaire
  ## pierre  "a"   "d"   "g"    "j"       "m"        
  ## ciseaux "c"   "f"   "i"    "l"       "o"

# Méthode 2 : par les noms
o1[c("pierre", "ciseaux"), ]
  ##         pouce index majeur annulaire auriculaire
  ## pierre  "a"   "d"   "g"    "j"       "m"        
  ## ciseaux "c"   "f"   "i"    "l"       "o"

# Méthode 3 : avec un vecteur logique
o1[c(TRUE, FALSE, TRUE), ]
  ##         pouce index majeur annulaire auriculaire
  ## pierre  "a"   "d"   "g"    "j"       "m"        
  ## ciseaux "c"   "f"   "i"    "l"       "o"

# Remarque : dans les trois cas, on extrait des lignes sans
# toucher aux colonnes donc on laisse une position vide après
# la virgule dans [, ]

Les deux premières méthodes permettent de modifier l’ordre des éléments ou de les répéter, mais pas la troisième :

o1
  ##         pouce index majeur annulaire auriculaire
  ## pierre  "a"   "d"   "g"    "j"       "m"        
  ## feuille "b"   "e"   "h"    "k"       "n"        
  ## ciseaux "c"   "f"   "i"    "l"       "o"

o1[c(3, 1, 1, 3), ]
  ##         pouce index majeur annulaire auriculaire
  ## ciseaux "c"   "f"   "i"    "l"       "o"        
  ## pierre  "a"   "d"   "g"    "j"       "m"        
  ## pierre  "a"   "d"   "g"    "j"       "m"        
  ## ciseaux "c"   "f"   "i"    "l"       "o"


o1[c("ciseaux", "pierre", "pierre", "ciseaux"), ]
  ##         pouce index majeur annulaire auriculaire
  ## ciseaux "c"   "f"   "i"    "l"       "o"        
  ## pierre  "a"   "d"   "g"    "j"       "m"        
  ## pierre  "a"   "d"   "g"    "j"       "m"        
  ## ciseaux "c"   "f"   "i"    "l"       "o"

o1[c(TRUE, FALSE, TRUE), ]
  ##         pouce index majeur annulaire auriculaire
  ## pierre  "a"   "d"   "g"    "j"       "m"        
  ## ciseaux "c"   "f"   "i"    "l"       "o"
# Note : il est impossible de changer l'ordre dans lequel apparaissent
# les éléments extraits (ni de les répéter) quand on utilise un vecteur
# logique pour mener l'extraction.

Ces différentes méthodes sont particulièrement utiles en pratique (cf. module 3):

  • l’extraction par les positions est à la base des tris sur une table de données ;
  • l’extraction avec un vecteur logique est à la base de la sélection d’observations ou de variables dans une table de données.

 

 

Cas pratique 2.7 Créer et sélectionner les éléments d’une matrice

  1. Déterminez la valeur, le type et les dimensions des matrices suivantes (sans utiliser le logiciel). Vérifiez ensuite ce qu’il en est.

    p1 <- matrix(1:10, ncol = 2)
    p2 <- matrix(1:10, nrow = 2, byrow = TRUE)
    p3 <- matrix(rep(c(TRUE, 1, "a"), times = 5), nrow = 3)
    p4 <- matrix(rep(c(TRUE, 1, "a"), each = 5), nrow = 3)

     

  2. On définit la matrice p5 <- matrix(15:1, nrow = 3). Sélectionnez l’élément en position 1, 4, puis toute la troisième ligne et toute la deuxième colonne. Que se passe-t-il quand vous tapez p5[c(1, 2), c(3, 4)] ?

     

  3. Assignez les noms c("Jacques", "Pierre", "Paul") et c("orange", "pomme", "poire", "banane", "abricot") aux lignes et aux colonnes de p5 respectivement. Que vaut la valeur au croisement de Pierre et de pomme ?

     

  4. (Difficile) Utilisez la fonction order() pour trier la matrice p5 selon les valeurs de sa première colonne pour obtenir :

      ##         orange pomme poire banane abricot
      ## Paul        13    10     7      4       1
      ## Pierre      14    11     8      5       2
      ## Jacques     15    12     9      6       3

     

     

 

Les listes : création et sélection

Du point de vue de la statistique appliquée, la principale limitation des matrices est qu’elles ne peuvent, comme les vecteurs, contenir qu’un seul type de données. Il est impossible de construire une matrice dont certaines variables sont de type numérique (par exemple l’âge des personnes enquêtées) et d’autres de type caractère (par exemple leur secteur d’activité). Les matrices ne constituent donc pas un type d’objet susceptible de stocker l’information statistique habituellement mobilisée dans les enquêtes sociales.

Les listes constituent en revanche un type d’objet beaucoup plus riche qui permet précisément de rassembler des types d’objets très différents : une liste peut contenir tous les types d’objet (vecteurs numériques, caractères, logiques, matrices, etc.), y compris d’autres listes. Cette très grande souplesse fait de la liste l’objet de prédilection pour stocker une information complexe et structurée, en particulier les résultats de procédures statistiques complexes (régression, classification, etc.).

Plus encore, le type d’objet utilisé pour stocker des données statistiques, le data.frame (cf. module 3), est un cas particulier de liste. La connaissance et la compréhension du fonctionnement des listes dans R facilite ainsi considérablement le travail sur des données statistiques.

 

La fonction list() crée une nouvelle liste.

s1 <- list(
  1:4
  , c("a","b","c")
  , TRUE
  , matrix(rnorm(4), ncol = 2)
)
s1
  ## [[1]]
  ## [1] 1 2 3 4
  ## 
  ## [[2]]
  ## [1] "a" "b" "c"
  ## 
  ## [[3]]
  ## [1] TRUE
  ## 
  ## [[4]]
  ##            [,1]       [,2]
  ## [1,]  1.9803999 -1.0441346
  ## [2,] -0.3672215  0.5697196

L’affichage d’une liste diffère sensiblement de celui d’une matrice ou d’un vecteur : on distingue deux niveaux de positions, d’abord celles indiquées entre double-crochets [[ puis celle indiquées entre crochets simples [.

Comme un vecteur, une liste a une longueur qui correspond à son nombre d’éléments au sens du nombre d’éléments intervenant dans la fonction list() (positions en double-crochets [[). Quand on affiche sa structure, R affiche également celle des éléments qui composent la liste.

# Caractéristiques de s1
length(s1)
  ## [1] 4
str(s1)
  ## List of 4
  ##  $ : int [1:4] 1 2 3 4
  ##  $ : chr [1:3] "a" "b" "c"
  ##  $ : logi TRUE
  ##  $ : num [1:2, 1:2] 1.98 -0.367 -1.044 0.57

On constate ici que la liste s1 comporte des éléments de type très différents : un vecteur de nombres entiers, un vecteur caractère, un vecteur logique et même une matrice numérique.

Comme pour les vecteurs, il est possible de nommer les éléments d’une liste, soit lors de sa création soit en utilisant la fonction names().

 # Affichage des noms de s1
names(s1)
  ## NULL

# Ajout de noms à s1
names(s1) <- c("chat", "chien", "lapin", "poisson rouge")
s1
  ## $chat
  ## [1] 1 2 3 4
  ## 
  ## $chien
  ## [1] "a" "b" "c"
  ## 
  ## $lapin
  ## [1] TRUE
  ## 
  ## $`poisson rouge`
  ##            [,1]       [,2]
  ## [1,]  1.9803999 -1.0441346
  ## [2,] -0.3672215  0.5697196
str(s1)
  ## List of 4
  ##  $ chat         : int [1:4] 1 2 3 4
  ##  $ chien        : chr [1:3] "a" "b" "c"
  ##  $ lapin        : logi TRUE
  ##  $ poisson rouge: num [1:2, 1:2] 1.98 -0.367 -1.044 0.57

# Définition directe d'une liste nommée
s2 <- list(
  "pierre" = 1:3
  , "feuille" = FALSE
  , "ciseaux" = letters[1:3]
)
s2
  ## $pierre
  ## [1] 1 2 3
  ## 
  ## $feuille
  ## [1] FALSE
  ## 
  ## $ciseaux
  ## [1] "a" "b" "c"

 

Plusieurs opérateurs permettent d’accéder aux éléments d’une liste :

  • [ renvoie la sous-liste correspondant aux indices, noms ou positions logiques demandés ;

    str(s1)
      ## List of 4
      ##  $ chat         : int [1:4] 1 2 3 4
      ##  $ chien        : chr [1:3] "a" "b" "c"
      ##  $ lapin        : logi TRUE
      ##  $ poisson rouge: num [1:2, 1:2] 1.98 -0.367 -1.044 0.57
    
     # Utilisation de [
    s1[1]
      ## $chat
      ## [1] 1 2 3 4
    
    str(s1[1])
      ## List of 1
      ##  $ chat: int [1:4] 1 2 3 4
    
    s1[c(2, 3)]
      ## $chien
      ## [1] "a" "b" "c"
      ## 
      ## $lapin
      ## [1] TRUE
    
    s1[-4]
      ## $chat
      ## [1] 1 2 3 4
      ## 
      ## $chien
      ## [1] "a" "b" "c"
      ## 
      ## $lapin
      ## [1] TRUE
    
    s1[c("lapin", "chien")]
      ## $lapin
      ## [1] TRUE
      ## 
      ## $chien
      ## [1] "a" "b" "c"
    
    s1[c(TRUE, FALSE, FALSE, TRUE)]
      ## $chat
      ## [1] 1 2 3 4
      ## 
      ## $`poisson rouge`
      ##            [,1]       [,2]
      ## [1,]  1.9803999 -1.0441346
      ## [2,] -0.3672215  0.5697196
  • [[ renvoie l’élément correspondant à l’indice ou au nom demandé (un seul indice ou un seul nom autorisé dans ce cas) ;

    str(s1)
      ## List of 4
      ##  $ chat         : int [1:4] 1 2 3 4
      ##  $ chien        : chr [1:3] "a" "b" "c"
      ##  $ lapin        : logi TRUE
      ##  $ poisson rouge: num [1:2, 1:2] 1.98 -0.367 -1.044 0.57
    
    # Utilisation de [[
    s1[[1]]
      ## [1] 1 2 3 4
    
    str(s1[[1]])
      ##  int [1:4] 1 2 3 4
    
    # Remarque : bien noter la différence avec s1[1]
    str(s1[1])
      ## List of 1
      ##  $ chat: int [1:4] 1 2 3 4
    # s1[1] renvoie une sous-liste, quand s1[[1]] renvoie
    # l'élément lui-même (ici un vecteur d'entiers)
    
    s1[[c(2, 4)]]
      ## Error in s1[[c(2, 4)]]: indice hors limites
    # Note : [[ ne permet de sélectionner qu'un seul élément
    # à la fois.
    
    s1[["lapin"]]
      ## [1] TRUE
  • $ renvoie l’élément correspondant au nom demandé (ne fonctionne qu’avec des listes nommées).

    str(s1)
      ## List of 4
      ##  $ chat         : int [1:4] 1 2 3 4
      ##  $ chien        : chr [1:3] "a" "b" "c"
      ##  $ lapin        : logi TRUE
      ##  $ poisson rouge: num [1:2, 1:2] 1.98 -0.367 -1.044 0.57
    
    # Utilisation de $
    s1$chat
      ## [1] 1 2 3 4
    
    str(s1$chat)
      ##  int [1:4] 1 2 3 4

Pour effectuer des opérations sur un élément d’une liste, il suffit de le sélectionner avec [[ ou $.

str(s1)
  ## List of 4
  ##  $ chat         : int [1:4] 1 2 3 4
  ##  $ chien        : chr [1:3] "a" "b" "c"
  ##  $ lapin        : logi TRUE
  ##  $ poisson rouge: num [1:2, 1:2] 1.98 -0.367 -1.044 0.57

# Opérations sur le premier élément de s1
s1[[1]]
  ## [1] 1 2 3 4
sum(s1[[1]])
  ## [1] 10
mean(s1$chat)
  ## [1] 2.5

 

Cas pratique 2.8 Créer et sélectionner les éléments d’une liste

  1. Devinez les valeurs, la longueur et la structure des trois listes suivantes, puis vérifiez-les dans le logiciel.

    t1 <- list("a", "b", 3, "d")
    t2 <- list(c("a", "b", 3, "d"))
    t3 <- list(list("a", "b"), 3, "d")

     

  2. On définit les objets suivants t4 <- rep(1:3, each = 4), t5 <- letters[c(5, 2, 3)] et t6 <- c(TRUE, FALSE, FALSE). Créez la liste t7 à partir de ces trois objets (dans l’ordre) et affectez lui les noms "Athos", "Porthos" et "Aramis". Proposez trois méthodes pour accéder au deuxième élément de t7.

     

  3. On définit la liste t8 <- list(matrix(1:6, nrow = 2), matrix(letters[1:6], ncol = 2)). Quelles sont les dimensions de chaque élément de la liste ? Combien le premier élément de la liste comporte-t-il de valeurs strictement supérieures à 1,8 ?

     

 

Les listes : opérations

Comme pour les vecteurs, il est possible de manipuler des listes en utilisant la fonction c() et les opérations ensemblistes (fonctions intersect() et setdiff()).

# Création de u1 et u2
u1 <- list(1:5, c("a", "b", "c"))
u1
  ## [[1]]
  ## [1] 1 2 3 4 5
  ## 
  ## [[2]]
  ## [1] "a" "b" "c"
u2 <- list(1:5, c(FALSE, TRUE, FALSE))
u2
  ## [[1]]
  ## [1] 1 2 3 4 5
  ## 
  ## [[2]]
  ## [1] FALSE  TRUE FALSE

# Concaténation de listes avec c()
c(u1, u2)
  ## [[1]]
  ## [1] 1 2 3 4 5
  ## 
  ## [[2]]
  ## [1] "a" "b" "c"
  ## 
  ## [[3]]
  ## [1] 1 2 3 4 5
  ## 
  ## [[4]]
  ## [1] FALSE  TRUE FALSE

# Opérations ensemblistes sur des listes
intersect(u1, u2)
  ## [[1]]
  ## [1] 1 2 3 4 5
setdiff(u1, u2)
  ## [[1]]
  ## [1] "a" "b" "c"
setdiff(u2, u1)
  ## [[1]]
  ## [1] FALSE  TRUE FALSE

 

D’autre part, la fonction lapply() permet d’appliquer la même fonction à chaque élément d’une liste.

# Création de la liste u3
u3 <- list(1:5, 6:10, 11:15)
u3
  ## [[1]]
  ## [1] 1 2 3 4 5
  ## 
  ## [[2]]
  ## [1]  6  7  8  9 10
  ## 
  ## [[3]]
  ## [1] 11 12 13 14 15

# Somme de chaque élément de la liste
lapply(u3, sum)
  ## [[1]]
  ## [1] 15
  ## 
  ## [[2]]
  ## [1] 40
  ## 
  ## [[3]]
  ## [1] 65
# Note : le premier argument de lapply() la liste
# sur les éléments de laquelle on souhaite appliquer
# une fonction et le second la fonction en question.

# Extraction du second élément de chaque élément
# de la liste
lapply(u3, function(x) x[2])
  ## [[1]]
  ## [1] 2
  ## 
  ## [[2]]
  ## [1] 7
  ## 
  ## [[3]]
  ## [1] 12

Quand la chose est possible, la fonction sapply() simplifie le résultat de la fonction lapply() pour obtenir en sortie une matrice ou un vecteur et non une liste.

u3
  ## [[1]]
  ## [1] 1 2 3 4 5
  ## 
  ## [[2]]
  ## [1]  6  7  8  9 10
  ## 
  ## [[3]]
  ## [1] 11 12 13 14 15

# Maximum de chaque élément de la liste avec lapply()
lapply(u3, max)
  ## [[1]]
  ## [1] 5
  ## 
  ## [[2]]
  ## [1] 10
  ## 
  ## [[3]]
  ## [1] 15

# Maximum de chaque élément de la liste avec sapply()
sapply(u3, max)
  ## [1]  5 10 15
# Note : la syntaxe de sapply() est identique à celle
# de lapply(), la seule différence est dans le type
# de résultat renvoyé.

# Extraction des premier et troisième éléments 
# de chaque élément de la liste
sapply(u3, function(x) x[c(1, 3)])
  ##      [,1] [,2] [,3]
  ## [1,]    1    6   11
  ## [2,]    3    8   13
# Note : quand sapply() ne peut pas renvoyer un vecteur, 
# il renvoie une matrice : quand sapply() ne peut pas renvoyer
# une matrice, il renvoie un liste. 

 

 

Cas pratique 2.9 Effectuer des opérations sur les listes

  1. On définit les listes v1 <- list(c(1, 2), c("a", "b", "c"), c(FALSE)) et v2 <- list(c("k", "j")). Comparez list(v1, v2) et c(v1, v2). D’où provient selon vous la différence ?

 

  1. On définit v3 <- c(v1, v2). Utilisez la fonction lapply() avec mode() pour déterminer le type de chaque élément de la liste v3. Comparez le résultat obtenu avec celui produit par sapply().

 

  1. En vous inspirant de la question précédente, extrayez automatiquement de v3 la sous-liste des objets de type caractère.