Réponses:
La définition du langage R est pratique pour répondre à ces types de questions:
R a trois opérateurs d'indexation de base, avec la syntaxe affichée par les exemples suivants
x[i] x[i, j] x[[i]] x[[i, j]] x$a x$"a"
Pour les vecteurs et les matrices, les
[[
formulaires sont rarement utilisés, bien qu'ils présentent de légères différences sémantiques par rapport au[
formulaire (par exemple, il supprime tout attribut de noms ou de dimnames, et cette correspondance partielle est utilisée pour les indices de caractères). Lors de l'indexation de structures multidimensionnelles avec un seul index,x[[i]]
oux[i]
retournera lei
e élément séquentiel dex
.Pour les listes, on utilise généralement
[[
pour sélectionner n'importe quel élément, tandis que[
renvoie une liste des éléments sélectionnés.Le
[[
formulaire ne permet de sélectionner qu'un seul élément à l'aide d'indices entiers ou de caractères, tandis qu'il[
permet l'indexation par des vecteurs. Notez cependant que pour une liste, l'index peut être un vecteur et que chaque élément du vecteur est appliqué tour à tour à la liste, au composant sélectionné, au composant sélectionné de ce composant, etc. Le résultat est toujours un élément unique.
[
toujours renvoyer une liste signifie que vous obtenez la même classe de sortie pour, x[v]
quelle que soit la longueur de v
. Par exemple, on peut vouloir lapply
plus d' un sous - ensemble d'une liste: lapply(x[v], fun)
. Si [
la liste des vecteurs de longueur un était supprimée, cela retournerait une erreur chaque fois qu'elle v
a une longueur un.
Les différences significatives entre les deux méthodes sont la classe des objets qu'ils retournent lorsqu'ils sont utilisés pour l'extraction et s'ils peuvent accepter une plage de valeurs, ou juste une seule valeur pendant l'affectation.
Prenons le cas de l'extraction de données dans la liste suivante:
foo <- list( str='R', vec=c(1,2,3), bool=TRUE )
Disons que nous aimerions extraire la valeur stockée par bool de foo et l'utiliser dans une if()
instruction. Cela illustrera les différences entre les valeurs de retour de []
et [[]]
quand elles sont utilisées pour l'extraction de données. La []
méthode renvoie des objets de la liste de classes (ou data.frame si foo était un data.frame) tandis que la [[]]
méthode retourne des objets dont la classe est déterminée par le type de leurs valeurs.
Ainsi, l'utilisation de la []
méthode donne les résultats suivants:
if( foo[ 'bool' ] ){ print("Hi!") }
Error in if (foo["bool"]) { : argument is not interpretable as logical
class( foo[ 'bool' ] )
[1] "list"
En effet, la []
méthode a renvoyé une liste et une liste n'est pas un objet valide à passer directement dans une if()
instruction. Dans ce cas, nous devons utiliser [[]]
car il retournera l'objet "nu" stocké dans 'bool' qui aura la classe appropriée:
if( foo[[ 'bool' ]] ){ print("Hi!") }
[1] "Hi!"
class( foo[[ 'bool' ]] )
[1] "logical"
La deuxième différence est que l' []
opérateur peut être utilisé pour accéder à une plage de créneaux dans une liste ou des colonnes dans une trame de données tandis que l' [[]]
opérateur est limité à l'accès à un seul créneau ou colonne. Considérons le cas de l'attribution de valeur à l'aide d'une deuxième liste bar()
:
bar <- list( mat=matrix(0,nrow=2,ncol=2), rand=rnorm(1) )
Disons que nous voulons écraser les deux derniers emplacements de foo avec les données contenues dans la barre. Si nous essayons d'utiliser l' [[]]
opérateur, voici ce qui se passe:
foo[[ 2:3 ]] <- bar
Error in foo[[2:3]] <- bar :
more elements supplied than there are to replace
En effet, [[]]
est limité à l'accès à un seul élément. Nous devons utiliser []
:
foo[ 2:3 ] <- bar
print( foo )
$str
[1] "R"
$vec
[,1] [,2]
[1,] 0 0
[2,] 0 0
$bool
[1] -0.6291121
Notez que bien que l'affectation ait réussi, les emplacements de foo ont conservé leur nom d'origine.
Les doubles crochets accèdent à un élément de la liste , tandis qu'un simple crochet vous donne une liste avec un seul élément.
lst <- list('one','two','three')
a <- lst[1]
class(a)
## returns "list"
a <- lst[[1]]
class(a)
## returns "character"
[]
extrait une liste, [[]]
extrait des éléments de la liste
alist <- list(c("a", "b", "c"), c(1,2,3,4), c(8e6, 5.2e9, -9.3e7))
str(alist[[1]])
chr [1:3] "a" "b" "c"
str(alist[1])
List of 1
$ : chr [1:3] "a" "b" "c"
str(alist[[1]][1])
chr "a"
Il suffit d'ajouter ici qui [[
est également équipé pour l' indexation récursive .
Cela a été laissé entendre dans la réponse de @JijoMatthew mais n'a pas été exploré.
Comme indiqué dans ?"[["
, la syntaxe comme x[[y]]
, où length(y) > 1
, est interprétée comme:
x[[ y[1] ]][[ y[2] ]][[ y[3] ]] ... [[ y[length(y)] ]]
Notez que cela ne change pas ce qui devrait être votre principal point de vue sur la différence entre [
et [[
- à savoir, que le premier est utilisé pour le sous- ensemble , et le dernier est utilisé pour extraire des éléments de liste unique.
Par exemple,
x <- list(list(list(1), 2), list(list(list(3), 4), 5), 6)
x
# [[1]]
# [[1]][[1]]
# [[1]][[1]][[1]]
# [1] 1
#
# [[1]][[2]]
# [1] 2
#
# [[2]]
# [[2]][[1]]
# [[2]][[1]][[1]]
# [[2]][[1]][[1]][[1]]
# [1] 3
#
# [[2]][[1]][[2]]
# [1] 4
#
# [[2]][[2]]
# [1] 5
#
# [[3]]
# [1] 6
Pour obtenir la valeur 3, nous pouvons faire:
x[[c(2, 1, 1, 1)]]
# [1] 3
Pour en revenir à la réponse de @ JijoMatthew ci-dessus, rappelez-vous r
:
r <- list(1:10, foo=1, far=2)
En particulier, cela explique les erreurs que nous avons tendance à obtenir lors d'une mauvaise utilisation [[
, à savoir:
r[[1:3]]
Erreur dans
r[[1:3]]
: l'indexation récursive a échoué au niveau 2
Étant donné que ce code a réellement essayé d'évaluer r[[1]][[2]][[3]]
et l'imbrication des r
arrêts au niveau un, la tentative d'extraction par indexation récursive a échoué [[2]]
, c'est-à-dire au niveau 2.
Erreur dans
r[[c("foo", "far")]]
: indice hors limites
Ici, R recherchait r[["foo"]][["far"]]
, ce qui n'existe pas, nous obtenons donc l'erreur d'indice hors limites.
Il serait probablement un peu plus utile / cohérent si ces deux erreurs transmettaient le même message.
Les deux sont des moyens de sous-ensemble. La parenthèse unique renverra un sous-ensemble de la liste, qui en soi sera une liste. c'est-à-dire: il peut ou non contenir plus d'un élément. D'un autre côté, un double crochet ne renverra qu'un seul élément de la liste.
-Le support unique nous donnera une liste. Nous pouvons également utiliser un seul crochet si nous souhaitons retourner plusieurs éléments de la liste. considérer la liste suivante: -
>r<-list(c(1:10),foo=1,far=2);
Veuillez maintenant noter la façon dont la liste est renvoyée lorsque j'essaie de l'afficher. Je tape r et appuie sur entrée
>r
#the result is:-
[[1]]
[1] 1 2 3 4 5 6 7 8 9 10
$foo
[1] 1
$far
[1] 2
Maintenant, nous allons voir la magie de la parenthèse simple: -
>r[c(1,2,3)]
#the above command will return a list with all three elements of the actual list r as below
[[1]]
[1] 1 2 3 4 5 6 7 8 9 10
$foo
[1] 1
$far
[1] 2
ce qui est exactement le même que lorsque nous avons essayé d'afficher la valeur de r à l'écran, ce qui signifie que l'utilisation d'un seul crochet a renvoyé une liste, où à l'index 1, nous avons un vecteur de 10 éléments, puis nous avons deux autres éléments avec des noms foo et loin. Nous pouvons également choisir de donner un seul index ou nom d'élément en entrée à la parenthèse unique. par exemple:
> r[1]
[[1]]
[1] 1 2 3 4 5 6 7 8 9 10
Dans cet exemple, nous avons donné un index "1" et en retour obtenu une liste avec un élément (qui est un tableau de 10 nombres)
> r[2]
$foo
[1] 1
Dans l'exemple ci-dessus, nous avons donné un index "2" et en retour obtenu une liste avec un élément
> r["foo"];
$foo
[1] 1
Dans cet exemple, nous avons passé le nom d'un élément et en retour une liste a été retournée avec un élément.
Vous pouvez également passer un vecteur de noms d'éléments comme: -
> x<-c("foo","far")
> r[x];
$foo
[1] 1
$far
[1] 2
Dans cet exemple, nous avons passé un vecteur avec deux noms d'éléments "foo" et "far"
En retour, nous avons obtenu une liste avec deux éléments.
En bref, la parenthèse simple vous renverra toujours une autre liste avec un nombre d'éléments égal au nombre d'éléments ou au nombre d'indices que vous passez dans la parenthèse simple.
En revanche, un double crochet ne renverra toujours qu'un seul élément. Avant de passer au double crochet, une note à garder à l'esprit.
NOTE:THE MAJOR DIFFERENCE BETWEEN THE TWO IS THAT SINGLE BRACKET RETURNS YOU A LIST WITH AS MANY ELEMENTS AS YOU WISH WHILE A DOUBLE BRACKET WILL NEVER RETURN A LIST. RATHER A DOUBLE BRACKET WILL RETURN ONLY A SINGLE ELEMENT FROM THE LIST.
Je vais citer quelques exemples. Veuillez noter les mots en gras et y revenir une fois que vous avez terminé avec les exemples ci-dessous:
Le double crochet vous renverra la valeur réelle à l'index (il ne retournera PAS une liste)
> r[[1]]
[1] 1 2 3 4 5 6 7 8 9 10
>r[["foo"]]
[1] 1
pour les crochets doubles si nous essayons de visualiser plusieurs éléments en passant un vecteur, cela entraînera une erreur simplement parce qu'il n'a pas été construit pour répondre à ce besoin, mais simplement pour renvoyer un seul élément.
Considérer ce qui suit
> r[[c(1:3)]]
Error in r[[c(1:3)]] : recursive indexing failed at level 2
> r[[c(1,2,3)]]
Error in r[[c(1, 2, 3)]] : recursive indexing failed at level 2
> r[[c("foo","far")]]
Error in r[[c("foo", "far")]] : subscript out of bounds
[]
renvoie une classe de liste même s'il ne s'agit que d'un seul chiffre est très peu intuitif. Ils auraient dû créer une autre syntaxe comme ([])
pour la liste et [[]]
accéder à l'élément réel est très bien. Je préfère penser [[]]
à la valeur brute comme dans d'autres langues.
Pour aider les débutants à naviguer dans le brouillard manuel, il peut être utile de voir la [[ ... ]]
notation comme une fonction de réduction - en d'autres termes, c'est quand vous voulez simplement `` obtenir les données '' d'un vecteur, d'une liste ou d'un bloc de données nommé. Il est conseillé de le faire si vous souhaitez utiliser les données de ces objets pour les calculs. Ces exemples simples vont illustrer.
(x <- c(x=1, y=2)); x[1]; x[[1]]
(x <- list(x=1, y=2, z=3)); x[1]; x[[1]]
(x <- data.frame(x=1, y=2, z=3)); x[1]; x[[1]]
Donc, à partir du troisième exemple:
> 2 * x[1]
x
1 2
> 2 * x[[1]]
[1] 2
iris[[1]]
retourne un vecteur, alors iris[1]
retourne un data.frame
Étant terminologique, l' [[
opérateur extrait l'élément d'une liste tandis que l' [
opérateur prend un sous - ensemble d'une liste.
Pour un autre cas d'utilisation concret, utilisez des crochets doubles lorsque vous souhaitez sélectionner un bloc de données créé par la split()
fonction. Si vous ne le savez pas, split()
regroupe une liste / trame de données en sous-ensembles en fonction d'un champ clé. Il est utile si vous souhaitez opérer sur plusieurs groupes, les tracer, etc.
> class(data)
[1] "data.frame"
> dsplit<-split(data, data$id)
> class(dsplit)
[1] "list"
> class(dsplit['ID-1'])
[1] "list"
> class(dsplit[['ID-1']])
[1] "data.frame"
Veuillez vous référer à l'explication détaillée ci-dessous.
J'ai utilisé la trame de données intégrée dans R, appelée mtcars.
> mtcars
mpg cyl disp hp drat wt ...
Mazda RX4 21.0 6 160 110 3.90 2.62 ...
Mazda RX4 Wag 21.0 6 160 110 3.90 2.88 ...
Datsun 710 22.8 4 108 93 3.85 2.32 ...
............
La ligne supérieure du tableau est appelée en-tête qui contient les noms des colonnes. Chaque ligne horizontale indique ensuite une ligne de données, qui commence par le nom de la ligne, puis est suivie par les données réelles. Chaque membre de données d'une ligne est appelé une cellule.
Pour récupérer des données dans une cellule, nous entrerions ses coordonnées de ligne et de colonne dans l'opérateur "[]" entre crochets. Les deux coordonnées sont séparées par une virgule. En d'autres termes, les coordonnées commencent par la position de la ligne, puis sont suivies d'une virgule et se terminent par la position de la colonne. L'ordre est important.
Par exemple 1: - Voici la valeur de la cellule de la première ligne, deuxième colonne de mtcars.
> mtcars[1, 2]
[1] 6
Par exemple 2: - En outre, nous pouvons utiliser les noms de ligne et de colonne au lieu des coordonnées numériques.
> mtcars["Mazda RX4", "cyl"]
[1] 6
Nous référençons une colonne de trame de données avec l'opérateur "[[]]" entre crochets doubles.
Par exemple 1: - Pour récupérer le vecteur de la neuvième colonne de l'ensemble de données intégré mtcars, nous écrivons mtcars [[9]].
mtcars [[9]] [1] 1 1 1 0 0 0 0 0 0 0 0 ...
Par exemple 2: - Nous pouvons récupérer le même vecteur de colonne par son nom.
mtcars [["am"]] [1] 1 1 1 0 0 0 0 0 0 0 0 ...