Comment utiliser correctement les listes dans R?

320

Bref historique: Beaucoup (la plupart?) De langages de programmation contemporains largement utilisés ont au moins une poignée d'ADT [types de données abstraits] en commun, en particulier,

  • chaîne (une séquence composée de caractères)

  • liste (une collection ordonnée de valeurs), et

  • type basé sur une carte (un tableau non ordonné qui mappe les clés aux valeurs)

Dans le langage de programmation R, les deux premières sont mises en œuvre comme characteret vector, respectivement.

Quand j'ai commencé à apprendre R, deux choses étaient évidentes presque dès le début: listest le type de données le plus important dans R (parce que c'est la classe parent pour le R data.frame), et deuxièmement, je ne pouvais tout simplement pas comprendre comment ils fonctionnaient, au moins pas assez bien pour les utiliser correctement dans mon code.

D'une part, il m'a semblé que le listtype de données de R était une implémentation simple de la carte ADT ( dictionaryen Python, NSMutableDictionaryen Objective C, hashen Perl et Ruby, object literalen Javascript, etc.).

Par exemple, vous les créez comme vous le feriez pour un dictionnaire Python, en passant des paires clé-valeur à un constructeur (ce qui n'est dictpas le cas en Python list):

x = list("ev1"=10, "ev2"=15, "rv"="Group 1")

Et vous accédez aux éléments d'une liste R comme vous le feriez pour ceux d'un dictionnaire Python, par exemple x['ev1']. De même, vous pouvez récupérer uniquement les «clés» ou simplement les «valeurs» en:

names(x)    # fetch just the 'keys' of an R list
# [1] "ev1" "ev2" "rv"

unlist(x)   # fetch just the 'values' of an R list
#   ev1       ev2        rv 
#  "10"      "15" "Group 1" 

x = list("a"=6, "b"=9, "c"=3)  

sum(unlist(x))
# [1] 18

mais les R listsont également différents des autres ADT de type carte (parmi les langues que j'ai apprises de toute façon). Je suppose que c'est une conséquence de la spécification initiale pour S, c'est-à-dire une intention de concevoir un DSL [langage spécifique au domaine] de données à partir de zéro.

trois différences significatives entre R lists et les types de mappage dans d'autres langages largement utilisés (par exemple, Python, Perl, JavaScript):

tout d'abord , lists dans R est une collection ordonnée , tout comme les vecteurs, même si les valeurs sont saisies (c'est-à-dire que les clés peuvent être n'importe quelle valeur lavable et pas seulement des entiers séquentiels). Presque toujours, le type de données de mappage dans d'autres langues n'est pas ordonné .

deuxièmement , lists peut être renvoyé à partir de fonctions même si vous n'avez jamais passé un listlorsque vous avez appelé la fonction, et même si la fonction qui a renvoyé le listne contient pas de listconstructeur ( explicite) (Bien sûr, vous pouvez gérer cela en pratique en encapsulant le résultat retourné dans un appel à unlist):

x = strsplit(LETTERS[1:10], "")     # passing in an object of type 'character'

class(x)                            # returns 'list', not a vector of length 2
# [1] list

Une troisième caractéristique particulière des R list: il ne semble pas qu'ils puissent être membres d'un autre ADT, et si vous essayez de le faire, le conteneur principal est contraint à a list. Par exemple,

x = c(0.5, 0.8, 0.23, list(0.5, 0.2, 0.9), recursive=TRUE)

class(x)
# [1] list

mon intention ici n'est pas de critiquer la langue ou la façon dont elle est documentée; de même, je ne dis pas qu'il y a quelque chose de mal avec la liststructure des données ou comment elle se comporte. Tout ce que je veux, c'est corriger, c'est ma compréhension de leur fonctionnement afin que je puisse les utiliser correctement dans mon code.

Voici le genre de choses que j'aimerais mieux comprendre:

  • Quelles sont les règles qui déterminent quand un appel de fonction retournera un list(par exemple, strsplitexpression récitée ci-dessus)?

  • Si je n'attribue pas explicitement de noms à un list(par exemple, list(10,20,30,40)) les noms par défaut sont-ils uniquement des entiers séquentiels commençant par 1? (Je suppose, mais je suis loin d'être certain que la réponse est oui, sinon nous ne pourrions pas contraindre ce type de listvecteur à un appel vers unlist.)

  • Pourquoi ces deux opérateurs différents,, []et [[]], renvoient-ils le même résultat?

    x = list(1, 2, 3, 4)

    les deux expressions renvoient "1":

    x[1]

    x[[1]]

  • pourquoi ces deux expressions ne renvoient-elles pas le même résultat?

    x = list(1, 2, 3, 4)

    x2 = list(1:4)

Veuillez ne pas me diriger vers la documentation R ( ?list, R-intro) - je l'ai lue attentivement et cela ne m'aide pas à répondre au type de questions que j'ai récitées ci-dessus.

(enfin, j'ai récemment appris et commencé à utiliser un package R (disponible sur CRAN) appelé hashqui implémente un comportement de type carte conventionnel via une classe S4; je peux certainement recommander ce package.)

doug
la source
3
Avec x = list(1, 2, 3, 4), les deux ne renvoient PAS le même résultat:, x[1]et x[[1]]. Le premier renvoie une liste et le second renvoie un vecteur numérique. En faisant défiler ci-dessous, il me semble que Dirk était le seul répondant à répondre correctement à cette question.
IRTFM
2
Je n'ai vu personne développer votre liste de façons qui, listdans R, n'est pas comme un hachage. J'en ai un de plus qui, à mon avis, mérite d'être noté. listdans R peut avoir deux membres avec le même nom de référence. Considérez que obj <- c(list(a=1),list(a=2))c'est valide et renvoie une liste avec deux valeurs nommées de 'a'. Dans ce cas, un appel à obj["a"]ne renverra que le premier élément de liste correspondant. Vous pouvez obtenir un comportement similaire (peut-être identique) à un hachage avec un seul élément par nom référencé en utilisant des environnements dans R. Par exemplex <- new.env(); x[["a"]] <- 1; x[["a"]] <- 2; x[["a"]]
russellpierce
1
J'ai relu cette publication avec les réponses trois fois au cours des 6 derniers mois et j'ai trouvé plus d'éclaircissements à chaque fois. Grande question et quelques bonnes réponses. Je vous remercie.
Rich Lysakowski PhD

Réponses:

150

Juste pour répondre à la dernière partie de votre question, car cela souligne vraiment la différence entre a listet vectorR:

Pourquoi ces deux expressions ne renvoient-elles pas le même résultat?

x = liste (1, 2, 3, 4); x2 = liste (1: 4)

Une liste peut contenir n'importe quelle autre classe comme chaque élément. Vous pouvez donc avoir une liste où le premier élément est un vecteur de caractères, le second un bloc de données, etc. Dans ce cas, vous avez créé deux listes différentes. xa quatre vecteurs, chacun de longueur 1. x2a 1 vecteur de longueur 4:

> length(x[[1]])
[1] 1
> length(x2[[1]])
[1] 4

Ce sont donc des listes complètement différentes.

Les listes R sont très similaires à une structure de données de carte de hachage en ce que chaque valeur d'index peut être associée à n'importe quel objet. Voici un exemple simple d'une liste qui contient 3 classes différentes (y compris une fonction):

> complicated.list <- list("a"=1:4, "b"=1:3, "c"=matrix(1:4, nrow=2), "d"=search)
> lapply(complicated.list, class)
$a
[1] "integer"
$b
[1] "integer"
$c
[1] "matrix"
$d
[1] "function"

Étant donné que le dernier élément est la fonction de recherche, je peux l'appeler ainsi:

> complicated.list[["d"]]()
[1] ".GlobalEnv" ...

Un dernier commentaire à ce sujet: il convient de noter que a data.frameest vraiment une liste (de la data.framedocumentation):

Une trame de données est une liste de variables du même nombre de lignes avec des noms de ligne uniques, étant donné la classe '"data.frame"'

C'est pourquoi les colonnes d'un data.framepeuvent avoir différents types de données, contrairement aux colonnes d'une matrice. À titre d'exemple, j'essaie ici de créer une matrice avec des chiffres et des caractères:

> a <- 1:4
> class(a)
[1] "integer"
> b <- c("a","b","c","d")
> d <- cbind(a, b)
> d
 a   b  
[1,] "1" "a"
[2,] "2" "b"
[3,] "3" "c"
[4,] "4" "d"
> class(d[,1])
[1] "character"

Notez que je ne peux pas changer le type de données dans la première colonne en numérique car la deuxième colonne a des caractères:

> d[,1] <- as.numeric(d[,1])
> class(d[,1])
[1] "character"
Shane
la source
4
Cela aide, merci. (Soit dit en passant, votre exemple sur la `` liste compliquée '', comme vous le savez peut-être déjà, est la manière standard de répliquer l'instruction `` switch '' en C ++, Java, etc. dans des langages qui n'en ont pas; probablement une bonne façon pour le faire en R quand j'en ai besoin). +1
doug
8
Oui, bien qu'il existe une switchfonction utile dans R qui peut être utilisée à cette fin (voir help(switch)).
Shane
63

Concernant vos questions, permettez-moi de les aborder dans l'ordre et de donner quelques exemples:

1 ) Une liste est retournée si et quand la déclaration de retour en ajoute une. Considérer

 R> retList <- function() return(list(1,2,3,4)); class(retList())
 [1] "list"
 R> notList <- function() return(c(1,2,3,4)); class(notList())
 [1] "numeric"
 R> 

2 ) Les noms ne sont tout simplement pas définis:

R> retList <- function() return(list(1,2,3,4)); names(retList())
NULL
R> 

3 ) Ils ne retournent pas la même chose. Votre exemple donne

R> x <- list(1,2,3,4)
R> x[1]
[[1]]
[1] 1
R> x[[1]]
[1] 1

x[1]renvoie le premier élément de x- qui est le même que x. Chaque scalaire est un vecteur de longueur un. Par contre x[[1]]retourne le premier élément de la liste.

4 ) Enfin, les deux sont différents entre eux créent respectivement une liste contenant quatre scalaires et une liste avec un seul élément (qui se trouve être un vecteur de quatre éléments).

Dirk Eddelbuettel
la source
1
Très utile, merci. (Concernant le point n ° 1 de votre réponse - je suis d'accord, mais je pensais à des éléments intégrés comme «strsplit», pas à des fonctions créées par l'utilisateur). En tout cas, +1 de moi.
doug
2
@doug À propos de l'élément n ° 1 Je pense que la seule façon est de vérifier l'aide pour une fonction spécifique, section Value. Comme dans ?strsplit: "Une liste de la même longueur que x". Mais vous devez considérer qu'il peut y avoir une fonction qui retourne des valeurs différentes en fonction des arguments (par exemple, sapply peut retourner une liste ou un vecteur).
Marek
34

Juste pour prendre un sous-ensemble de vos questions:

Cet article sur l'indexation aborde la question de la différence entre []et [[]].

En bref, [[]] sélectionne un seul élément dans une liste et []renvoie une liste des éléments sélectionnés. Dans votre exemple, l' x = list(1, 2, 3, 4)'élément 1 est un entier unique mais x[[1]]renvoie un seul 1 et x[1]renvoie une liste avec une seule valeur.

> x = list(1, 2, 3, 4)
> x[1]
[[1]]
[1] 1

> x[[1]]
[1] 1
JD Long
la source
Soit dit en passant, A = array( 11:16, c(2,3) ); A[5]est 15, dans le tableau plat ?!
denis
13

Une des raisons pour lesquelles les listes fonctionnent comme elles le font (ordonnées) est de répondre au besoin d'un conteneur ordonné qui peut contenir n'importe quel type à n'importe quel nœud, ce que les vecteurs ne font pas. Les listes sont réutilisées à diverses fins dans R, y compris la formation de la base de a data.frame, qui est une liste de vecteurs de type arbitraire (mais de même longueur).

Pourquoi ces deux expressions ne renvoient-elles pas le même résultat?

x = list(1, 2, 3, 4); x2 = list(1:4)

Pour ajouter à la réponse de @ Shane, si vous souhaitez obtenir le même résultat, essayez:

x3 = as.list(1:4)

Ce qui contraint le vecteur 1:4dans une liste.

Alex Brown
la source
11

Juste pour ajouter un point à cela:

R a une structure de données équivalente à la dictée Python dans le hashpackage . Vous pouvez en lire plus dans cet article de blog du groupe Open Data . Voici un exemple simple:

> library(hash)
> h <- hash( keys=c('foo','bar','baz'), values=1:3 )
> h[c('foo','bar')]
<hash> containing 2 key-value pairs.
  bar : 2
  foo : 1

En termes de convivialité, la hashclasse est très similaire à une liste. Mais les performances sont meilleures pour les grands ensembles de données.

Shane
la source
1
Je connais le paquet de hachage - il est mentionné dans ma question d'origine comme un proxy approprié pour le type de hachage traditionnel.
doug
Notez également que l'utilisation de hash :: hash est d'un utilité discutable par rapport aux environnements hachés, rpubs.com/rpierce/hashBenchmarks .
russellpierce
9

Vous dites:

D'autre part, des listes peuvent être renvoyées à partir de fonctions même si vous n'avez jamais passé de liste lorsque vous avez appelé la fonction, et même si la fonction ne contient pas de constructeur List, par exemple,

x = strsplit(LETTERS[1:10], "") # passing in an object of type 'character'
class(x)
# => 'list'

Et je suppose que vous suggérez que c'est un problème (?). Je suis ici pour vous dire pourquoi ce n'est pas un problème :-). Votre exemple est un peu simple, en ce sens que lorsque vous effectuez le fractionnement de chaîne, vous avez une liste avec des éléments de 1 élément, vous savez donc que x[[1]]c'est la même chose que unlist(x)[1]. Et si le résultat strsplitrenvoyait des résultats de longueur différente dans chaque bac. Le simple retour d'un vecteur (par rapport à une liste) ne fera rien du tout.

Par exemple:

stuff <- c("You, me, and dupree",  "You me, and dupree",
           "He ran away, but not very far, and not very fast")
x <- strsplit(stuff, ",")
xx <- unlist(strsplit(stuff, ","))

Dans le premier cas ( x: qui retourne une liste), vous pouvez dire ce que la 2ème « partie » de la 3ème corde était, par exemple: x[[3]][2]. Comment pourriez-vous faire de même en utilisant xxmaintenant que les résultats ont été "démêlés" ( unlist-ed)?

Steve Lianoglou
la source
5
x = list(1, 2, 3, 4)
x2 = list(1:4)
all.equal(x,x2)

n'est pas le même parce que 1: 4 est identique à c (1,2,3,4). Si vous voulez qu'ils soient identiques, alors:

x = list(c(1,2,3,4))
x2 = list(1:4)
all.equal(x,x2)
JeremyS
la source
4

Il s'agit d'une question très ancienne, mais je pense qu'une nouvelle réponse pourrait apporter une certaine valeur car, à mon avis, personne n'a directement répondu à certaines des préoccupations du PO.

Malgré ce que suggèrent les réponses acceptées, les listobjets en R ne sont pas des cartes de hachage. Si vous voulez faire un parallèle avec python, ce listsont plutôt des pythons list(ou des tuples en fait).

Il est préférable de décrire comment la plupart des objets R sont stockés en interne (le type C d'un objet R est SEXP). Ils sont constitués essentiellement de trois parties:

  • un en-tête, qui déclare le type R de l'objet, la longueur et quelques autres métadonnées;
  • la partie données, qui est un tableau standard alloué en tas C (bloc de mémoire contigu);
  • les attributs, qui sont une liste liée nommée de pointeurs vers d'autres objets R (ou NULLsi l'objet n'a pas d'attributs).

D'un point de vue interne, il y a peu de différence entre a listet un numericvecteur par exemple. Les valeurs qu'ils stockent sont simplement différentes. Décomposons deux objets dans le paradigme que nous avons décrit précédemment:

x <- runif(10)
y <- list(runif(10), runif(3))

Pour x:

  • L'en-tête indiquera que le type est numeric(REALSXP dans le côté C), la longueur est 10 et d'autres choses.
  • La partie de données sera un tableau contenant 10 doublevaleurs.
  • Les attributs le sont NULL, car l'objet n'en a pas.

Pour y:

  • L'en-tête dira que le type est list( VECSXPdans le côté C), la longueur est 2 et d'autres choses.
  • La partie de données sera un tableau contenant 2 pointeurs vers deux types SEXP, pointant vers la valeur obtenue par runif(10)etrunif(3)respectivement.
  • Les attributs sont NULL, comme pour x.

Donc, la seule différence entre un numericvecteur et un listest que la numericpartie de données est constituée de doublevaleurs, tandis que pour lelist partie de données est un tableau de pointeurs vers d'autres objets R.

Que se passe-t-il avec les noms? Eh bien, les noms ne sont que quelques-uns des attributs que vous pouvez attribuer à un objet. Voyons l'objet ci-dessous:

z <- list(a=1:3, b=LETTERS)
  • L'en-tête dira que le type est list( VECSXPdans le côté C), la longueur est 2 et d'autres choses.
  • La partie de données sera un tableau contenant 2 pointeurs vers deux types SEXP, pointant vers la valeur obtenue par 1:3et LETTERSrespectivement.
  • Les attributs sont maintenant présents et sont un namescomposant qui est un characterobjet R avec une valeur c("a","b").

À partir du niveau R, vous pouvez récupérer les attributs d'un objet avec la attributesfonction.

La valeur-clé typique d'une carte de hachage dans R n'est qu'une illusion. Quand tu dis:

z[["a"]]

c'est ce qui se passe:

  • la [[fonction de sous - ensemble est appelée;
  • l'argument de la fonction ( "a") est de type character, donc la méthode est chargée de rechercher une telle valeur dans l' namesattribut (s'il est présent) de l'objet z;
  • si l' namesattribut n'est pas là, NULLest retourné;
  • s'il est présent, la "a"valeur y est recherchée. Si "a"n'est pas un nom de l'objet, NULLest retourné;
  • s'il est présent, la position est déterminée (1 dans l'exemple). Ainsi, le premier élément de la liste est retourné, c'est-à-dire l'équivalent de z[[1]].

La recherche par valeur-clé est plutôt indirecte et toujours positionnelle. Aussi, utile de garder à l'esprit:

  • dans les cartes de hachage, la seule limite qu'une clé doit avoir est qu'elle doit être lavable . namesdans R doit être des chaînes ( charactervecteurs);
  • dans les cartes de hachage, vous ne pouvez pas avoir deux clés identiques. Dans R, vous pouvez attribuer namesà un objet avec des valeurs répétées. Par exemple:

    names(y) <- c("same", "same")

    est parfaitement valide en R. Lorsque vous essayez, y[["same"]]la première valeur est récupérée. Vous devez savoir pourquoi à ce stade.

En conclusion, la possibilité de donner des attributs arbitraires à un objet vous donne l'apparence de quelque chose de différent d'un point de vue externe. Mais les R listne sont en aucun cas des cartes de hachage.

nicola
la source
2

Concernant les vecteurs et le concept de hachage / tableau d'autres langues:

  1. Les vecteurs sont les atomes de R. Par exemple, rpois(1e4,5)(5 nombres aléatoires), numeric(55)(vecteur nul de longueur 55 sur les doubles) et character(12)(12 chaînes vides), sont tous "de base".

  2. Soit des listes, soit des vecteurs names.

    > n = numeric(10)
    > n
     [1] 0 0 0 0 0 0 0 0 0 0
    > names(n)
    NULL
    > names(n) = LETTERS[1:10]
    > n
    A B C D E F G H I J 
    0 0 0 0 0 0 0 0 0 0
  3. Les vecteurs exigent que tout soit du même type de données. Regarde ça:

    > i = integer(5)
    > v = c(n,i)
    > v
    A B C D E F G H I J           
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
    > class(v)
    [1] "numeric"
    > i = complex(5)
    > v = c(n,i)
    > class(v)
    [1] "complex"
    > v
       A    B    C    D    E    F    G    H    I    J                          
    0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i 0+0i
  4. Les listes peuvent contenir différents types de données, comme le montrent d'autres réponses et la question du PO lui-même.

J'ai vu des langages (ruby, javascript) dans lesquels les "tableaux" peuvent contenir des types de données variables, mais par exemple en C ++, les "tableaux" doivent être tous du même type de données. Je crois que c'est une question de vitesse / efficacité: si vous en avez un, numeric(1e6)vous connaissez sa taille et l'emplacement de chaque élément a priori ; si la chose peut contenir"Flying Purple People Eaters" dans une tranche inconnue, alors vous devez réellement analyser des choses pour connaître les faits de base à ce sujet.

Certaines opérations R standard ont également plus de sens lorsque le type est garanti. Par exemple, cumsum(1:9)cela a du sens alors cumsum(list(1,2,3,4,5,'a',6,7,8,9))que non, sans que le type soit garanti double.


Quant à votre deuxième question:

Les listes peuvent être renvoyées par les fonctions même si vous n'avez jamais passé dans une liste lorsque vous avez appelé la fonction

Les fonctions renvoient des types de données différents de ceux qu'ils saisissent tout le temps. plotrenvoie un tracé même s'il ne prend pas de tracé en entrée. Argrenvoie un numericmême s'il a accepté uncomplex . Etc.

(Et comme pour strsplit: le code source est ici .)

isomorphismes
la source
2

Bien que cette question soit assez ancienne, je dois dire qu'elle touche exactement les connaissances qui me manquaient lors de mes premiers pas dans R - c'est-à-dire comment exprimer des données dans ma main en tant qu'objet dans R ou comment choisir parmi des objets existants. Il n'est pas facile pour un novice R de penser "dans une boîte R" dès le début.

J'ai donc moi-même commencé à utiliser des béquilles ci-dessous, ce qui m'a beaucoup aidé à découvrir quel objet utiliser pour quelles données, et essentiellement à imaginer une utilisation réelle.

Bien que je ne donne pas de réponses exactes à la question, le court texte ci-dessous pourrait aider le lecteur qui vient de commencer avec R et pose des questions similaires.

  • Vecteur atomique ... J'ai appelé cette "séquence" pour moi, pas de direction, juste une séquence du même type. [sous-ensembles.
  • Vector ... séquence avec une direction à partir de 2D, [sous - ensembles.
  • Matrice ... tas de vecteurs de même longueur formant des lignes ou des colonnes, [ sous ensembles par lignes et colonnes, ou par séquence.
  • Matrices ... matrices en couches formant la 3D
  • Dataframe ... une table 2D comme dans Excel, où je peux trier, ajouter ou supprimer des lignes ou des colonnes ou faire de l'arit. opérations avec eux, seulement après un certain temps, j'ai vraiment reconnu que dataframe est une implémentation intelligente d' listoù je peux sous-ensemble en utilisant des [lignes et des colonnes, mais même en utilisant [[.
  • Liste ... pour m'aider, j'ai pensé à la liste à partir de tree structurelaquelle [i]sélectionne et renvoie des branches entières et [[i]]renvoie un élément de la branche. Et parce que c'est le cas tree like structure, vous pouvez même utiliser un index sequencepour adresser chaque feuille sur un très complexe en listutilisant son [[index_vector]]. Les listes peuvent être simples ou très complexes et peuvent mélanger différents types d'objets en un seul.

Donc, listsvous pouvez vous retrouver avec plus de façons de sélectionner un en leaffonction de la situation, comme dans l'exemple suivant.

l <- list("aaa",5,list(1:3),LETTERS[1:4],matrix(1:9,3,3))
l[[c(5,4)]] # selects 4 from matrix using [[index_vector]] in list
l[[5]][4] # selects 4 from matrix using sequential index in matrix
l[[5]][1,2] # selects 4 from matrix using row and column in matrix

Cette façon de penser m'a beaucoup aidé.

Petr Matousu
la source
1

Si cela aide, j'ai tendance à concevoir des "listes" en R comme des "enregistrements" dans d'autres langues pré-OO:

  • ils ne font aucune hypothèse sur un type global (ou plutôt le type de tous les enregistrements possibles de n'importe quel nom d'arité et de champ est disponible).
  • leurs champs peuvent être anonymes (alors vous y accédez par ordre de définition strict).

Le nom "record" entrerait en conflit avec la signification standard de "records" (alias lignes) dans le langage de la base de données, et c'est peut-être la raison pour laquelle leur nom se suggère lui-même: sous forme de listes (de champs).

Francisco J. Valverde Albacete
la source
1

pourquoi ces deux opérateurs différents,, [ ]et [[ ]], renvoient-ils le même résultat?

x = list(1, 2, 3, 4)
  1. [ ]fournit une opération de sous-réglage. En général, le sous-ensemble de tout objet aura le même type que l'objet d'origine. Par conséquent, x[1] fournit une liste. De même x[1:2]est un sous-ensemble de la liste d'origine, donc c'est une liste. Ex.

    x[1:2]
    
    [[1]] [1] 1
    
    [[2]] [1] 2
  2. [[ ]]sert à extraire un élément de la liste. x[[1]]est valide et extrayez le premier élément de la liste. x[[1:2]]n'est pas valide car [[ ]] ne fournit pas de sous-paramètre comme [ ].

     x[[2]] [1] 2 
    
    > x[[2:3]] Error in x[[2:3]] : subscript out of bounds
HariG
la source