10. Listes
Jusqu’à présent, on n’a manipulé que des objets homogènes, c’est à dire contenant des valeurs de même nature (numérique, logique, chaîne de caractères). Les listes permettent de dépasser cette contrainte.
10.1. Caractéristiques de base
Comme le vecteur, la list
est une séquence ordonnée d’éléments, possédant les caractéristiques suivantes:
elle peut être hétérogène
elle est indexable, c’est à dire qu’on peut accéder à ses éléments par leur position
on peut en extraire des sous listes (indexation sur une plage de positions)
on peut nommer ses éléments, ce qui autorise une indexation plus lisible que par position
La list
peut être hétérogène, et il n’y a donc aucune contrainte sur la nature des éléments qui la constituent. Par exemple, une liste peut être constituée avec:
un vecteur numérique
une valeur logique
une matrice
un
array
de chaînes de caractèresune fonction
etc.
On crée une list
avec la fonction list()
.
Important
Pour rappel, un vecteur est créé avec la fonction c()
, un array
avec la fonction array()
et une matrice avec la fonction matrix()
.
Un exemple de liste:
> Lst <- list(name="Fred", wife="Mary", no.children=3, child.ages=c(4,7,9))
> names(Lst)
[1] "name" "wife" "no.children" "child.ages"
Important
Le caractère .
est employé en R comme n’importe quel autre caractère alphanumérique pour la création de noms de variables ou de fonctions. Il ne possède pas comme dans d’autres langages (Python, Java, etc…) une signification particulière. Pour ces langages orientés objet, le .
sépare les objets des méthodes qui leur sont associées.
On pourrait également construire la même liste en 2 étapes:
> Lst <- list("Fred", "Mary", 3, c(4,7,9))
> names(Lst) <- c("name", "wife", "no.children", "child.ages")
Une list
est une structure dite récursive car elle peut contenir d’autres listes:
> x <- list(list(list(list())))
> str(x)
List of 1
$ :List of 1
..$ :List of 1
.. ..$ : list()
L’utilisation moderne de R fait un emploi massif de la data frame, qui est une super structure de la list
et il est peu courant d’avoir à travailler directement sur une list
. Il est cependant utile d’avoir vu quelques opérations élémentaires, tout en se souvenant qu’il y a probablement une bien meilleure façon de faire.
L’opérateur d’indexation de la liste est le double crochet [
et ]
:
> Lst[[1]]
[1] "Fred"
> Lst[[4]]
[1] 4 7 9
Chaque élément de la list
peut lui même être indexé suivant les règles vues précédemment. Puisque Lst[[4]]
est un vecteur, on accède à ses éléments avec l’opérateur d’indexation du vecteur:
> Lst[[4]][1]
[1] 4
La fonction length()
retourne le nombre d’éléments de la list
:
> length(Lst)
[1] 4
Les éléments de la list
peuvent être nommés et accédés via l’opérateur $
avec la syntaxe name$component_name
. Ainsi :
Lst$name
est une écriture allégée deLst[[1]]
et retourne la chaîne de caractèresFred
Lst$wife
est une écriture allégée deLst[[2]]
et retourne la chaîne de caractèresMary
Lst$child.ages[1]
est une écriture allégée deLst[[4]][1]
et retourne l’entier4
Le code correspondant:
> Lst$name
[1] "Fred"
> Lst$wife
[1] "Mary"
> Lst$child.ages[1]
[1] 4
Si on doit extraire des éléments programmatiquement, l’opérateur d’indexation de liste [ ]
est indispensable. Lst[["name"]]
retourne le même résultat que Lst$name
:
> x <- "name"
> Lst[[x]]
[1] "Fred"
Avertissement
Lst[[1]]
et Lst[1]
ne retournent pas la même chose. [[ ]]
est utilisé pour extraire un élément de la list
, alors que [ ]
retourne une list
constituée du premier élément de Lst
.
> class(Lst[[1]])
[1] "character"
> class(Lst[1])
[1] "list"
Astuce
On peut utiliser une abbréviation (non ambigüe) des noms associés à la syntaxe
name$component_name
. Par exemple,Lst$name
peut être raccourci enLst$na
mais pas enLst$n
puisqu’il y aurait ambigïté avecLst$no.children
.
> Lst$name
[1] "Fred"
> Lst$na
[1] "Fred"
> Lst$n
NULL
10.2. Construction et modification de listes
On peut créer une liste avec la fonction list()
avec une instruction de la forme:
> Lst <- list(name_1=object_1, …, name_m=object_m)
Avertissement
On peut omettre les noms en passant uniquement les objets constitutifs de la list
mais ce n’est pas une bonne pratique.
On peut construire un vecteur constitué des éléments de la list
avec la fonction unlist()
:
> x <- list(1,2)
> x
[[1]]
[1] 1
[[2]]
[1] 2
> unlist(x)
[1] 1 2
L’opération réciproque, c’est à dire la conversion d’un vecteur en list
se fait avec la fonction de coercition as.list()
:
> as.list(1:2)
[[1]]
[1] 1
[[2]]
[1] 2
Les list
, comme toutes les séquences ordonnées, peuvent être « étendues » par ajout d’éléments:
> Lst[5] <- list(matrix(1:6, nrow=2))
> Lst
$name
[1] "Fred"
$wife
[1] "Mary"
$no.children
[1] 3
$child.ages
[1] 4 7 9
[[5]]
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
Ajouter un élément de cette façon ne permet pas de le nommer:
> names(Lst)
[1] "name" "wife" "no.children" "child.ages" ""
Il faut le faire « manuellement »:
> names(Lst)[5] <- c("mat")
> names(Lst)
[1] "name" "wife" "no.children" "child.ages" "mat"
> Lst
$name
[1] "Fred"
$wife
[1] "Mary"
$no.children
[1] 3
$child.ages
[1] 4 7 9
$mat
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
10.2.1. Concaténation de list
Jusqu’à présent, la fonction de concaténation c()
n’a été utilisée que pour les vecteurs, mais est utile pour d’autres structures de données. L’objet créé est de même nature que les arguments passés à c()
:
> listA <- list(letters[1:3])
> class(listA)
[1] "list"
> listA
[[1]]
[1] "a" "b" "c"
> listB <- list(letters[4:6])
> listC <- list(letters[7:9])
> listABC <- c(listA, listB, listC)
> class(list.ABC)
[1] "list"
> list.ABC
[[1]]
[1] "a" "b" "c"
[[2]]
[1] "d" "e" "f"
[[3]]
[1] "g" "h" "i"