.. include:: weblinks.txt .. _lists: 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. 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ères - une fonction - etc. On crée une ``list`` avec la fonction :func:`list`. .. important:: Pour rappel, un vecteur est créé avec la fonction :func:`c`, un ``array`` avec la fonction :func:`array` et une matrice avec la fonction :func:`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 :func:`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 de ``Lst[[1]]`` et retourne la chaîne de caractères ``Fred`` - ``Lst$wife`` est une écriture allégée de ``Lst[[2]]`` et retourne la chaîne de caractères ``Mary`` - ``Lst$child.ages[1]`` est une écriture allégée de ``Lst[[4]][1]`` et retourne l'entier ``4`` 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" .. warning:: ``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``. .. code-block:: r > class(Lst[[1]]) [1] "character" > class(Lst[1]) [1] "list" .. tip:: 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 en ``Lst$na`` mais pas en ``Lst$n`` puisqu'il y aurait ambigïté avec ``Lst$no.children``. .. code-block:: r > Lst$name [1] "Fred" > Lst$na [1] "Fred" > Lst$n NULL Construction et modification de listes -------------------------------------- On peut créer une liste avec la fonction :func:`list` avec une instruction de la forme:: > Lst <- list(name_1=object_1, …, name_m=object_m) .. warning:: 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 :func:`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 :func:`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 Concaténation de ``list`` ......................... Jusqu'à présent, la fonction de concaténation :func:`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 à :func:`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"