La différence entre crochets [] et les doubles crochets [[]] pour l'accès aux éléments d'une liste ou d'un dataframe

R fournit deux méthodes différentes pour accéder aux éléments d'une liste ou aux données.frame-les opérateurs [] et [[]] .

Quelle est la différence entre les deux? Dans quelles situations dois-je utiliser l'un par rapport à l'autre?

422
demandé sur Gregor 2009-07-23 07:33:18

11 réponses

Le Langage R Définition est à portée de main pour répondre à ces types de questions:

R a trois opérateurs d'indexation de base, avec syntaxe affichée par les exemples suivants

"151900920"

Pour les vecteurs et les matrices, les formes [[ sont rarement utilisé, bien qu'ils présentent quelques légères différences sémantiques par rapport à la forme [ (par exemple, il supprime tout nom ou attribut dimnames, et que l'appariement partiel est utilisé pour les indices de caractères). Lors de l'indexation de structures multidimensionnelles avec un seul indice, x[[i]] ou x[i] retournera le i e élément séquentiel de x .

Pour les listes, on utilise généralement [[ pour sélectionner un seul élément, tandis que [ renvoie une liste des éléments sélectionnés.

La forme [[ ne permet de sélectionner qu'un seul élément à l'aide d'indices entiers ou de caractères, tandis que la forme [ permet l'indexation par vecteurs. Notez bien que pour une liste, l'indice peut être un vecteur et chaque élément du vecteur est appliquée à son tour à la liste, le composant sélectionné, le composant sélectionné cet élément, et ainsi de suite. Le résultat est toujours un élément unique.

270
répondu ars 2018-09-21 13:41:06

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'assignation.

examiner le cas de l'extraction de données sur 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 à l'intérieur d'une instruction if() . Cela permettra d'illustrer l' différences entre les valeurs de retour de [] et [[]] lorsqu'elles sont utilisées pour l'extraction de données. La méthode [] renvoie des objets de la liste de classe (ou des données.si foo était une donnée.frame) tandis que la méthode [[]] renvoie 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"

c'est parce que la méthode [] et une liste n'est pas valide objet de passer directement dans un if() . Dans ce cas, nous devons utiliser [[]] parce qu'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 gamme de slots dans une liste ou des colonnes dans un cadre de données tandis que l'opérateur [[]] est limité à accéder à un simple fente ou colonne. Considérons le cas de l'assignation de valeur en utilisant une deuxième liste, bar() :

bar <- list( mat=matrix(0,nrow=2,ncol=2), rand=rnorm(1) )

disons que nous voulons écraser les deux dernières fentes de foo avec les données contenues dans la barre. Si nous essayons d'utiliser l'opérateur [[]] , c'est ce qui se passe:

foo[[ 2:3 ]] <- bar
Error in foo[[2:3]] <- bar : 
more elements supplied than there are to replace

parce que [[]] 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 été réussie, les emplacements dans foo ont gardé leurs noms originaux.

147
répondu Sharpie 2009-07-23 04:06:55

double brackets accède à une liste element , tandis qu'un simple bracket vous renvoie 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"
89
répondu medriscoll 2014-06-03 20:18:22

[] 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"
39
répondu Brad Gilbert 2009-07-23 04:04:36

De Hadley Wickham:

From Hadley Wickham

ma modification (d'apparence merdique) à montrer en utilisant tidyverse / purrr:

enter image description here

17
répondu jzadra 2018-05-14 22:54:11

vient d'ajouter ici que [[ est également équipé pour indexation récursive .

cela a été évoqué dans la réponse de @JijoMatthew mais pas exploré.

comme noté dans ?"[[" , syntaxe comme x[[y]] , où length(y) > 1 , est interprété comme:

x[[ y[1] ]][[ y[2] ]][[ y[3] ]] ... [[ y[length(y)] ]]

notez que ce ne change pas ce qui devrait être votre principal avantage sur la différence entre [ et [[ , c'est-à-dire que le premier est utilisé pour sous-ensemble , et le second est utilisé pour extraction éléments de la 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 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 quand mal utiliser [[ , à savoir:

r[[1:3]]

erreur dans r[[1:3]] : échec de l'indexation récursive au niveau 2

étant donné que ce code a effectivement tenté d'évaluer r[[1]][[2]][[3]] , et que l'imbrication de r s'arrête au niveau un, la tentative d'extraction par indexation récursive a échoué au niveau [[2]] , c'est-à-dire au niveau 2.

Erreur dans r[[c("foo", "far")]] : indice hors limites

ici, R cherchait r[["foo"]][["far"]] , qui n'existe pas, donc nous obtenons l'indice hors erreur de limites.

il serait probablement un peu plus utile/cohérent que ces deux erreurs donnent le même message.

15
répondu MichaelChirico 2016-04-30 20:43:24

les deux sont des façons de sous-traiter. Le seul support retourne un sous-ensemble de la liste, ce qui en soi est une liste. ie: il peut ou ne peut pas contenir plus d'un élément. D'un autre côté, un double bracket ne retournera qu'un seul élément de la liste.

- simple bracket nous donnera une liste. Nous pouvons également utiliser un seul bracket si nous voulons retourner plusieurs éléments de la liste. considérons la liste suivante: -

>r<-list(c(1:10),foo=1,far=2);

Maintenant s'il vous plaît noter la façon dont la liste est renvoyée lorsque j'essaie de l'afficher. I tapez r et appuyez 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 mono bracket: -

>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

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 bracket a retourné 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 far. Nous pouvons également choisissez de donner un index ou un nom d'élément comme entrée dans le crochet 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 seul élément.

vous pouvez aussi 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 seul support vous ramène toujours une autre liste avec un nombre d'éléments égal au nombre d'éléments ou d'indices vous passer dans le seul support.

en revanche, un double bracket ne retournera toujours qu'un seul élément. Avant de passer à double bracket 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 vous donner quelques exemples. Veuillez garder en note les mots en gras et revenir après vous avez terminé avec les exemples ci-dessous:

double bracket vous retournera la valeur réelle à l'index.(Il va PAS retour 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 voir plus d'un éléments en passant un vecteur, il en résultera une erreur juste parce qu'il n'a pas été construit pour répondre à ce besoin, mais juste pour retourner un élément unique.

Envisager la suite de

> 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
14
répondu Jijo Mathew 2014-08-30 13:48:27

pour aider les débutants à naviguer dans le brouillard manuel, il pourrait être utile de voir la notation [[ ... ]] comme une fonction s'effondrant - en d'autres termes, c'est quand vous voulez juste "obtenir les données" à partir d'un vecteur nommé, liste ou base de données. Il est bon de le faire si vous voulez utiliser les données de ces objets pour les calculs. Ces exemples simples en sont une illustration.

(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]]

ainsi du troisième exemple:

> 2 * x[1]
  x
1 2
> 2 * x[[1]]
[1] 2
12
répondu Redfoot 2014-05-18 14:33:09

pour un autre cas concret d'utilisation, Utilisez des crochets doubles lorsque vous voulez sélectionner un cadre de données créé par la fonction split() . Si vous ne savez pas, split() regroupe une liste/base de données en sous-ensembles basés sur un champ Clé. C'est utile lorsque vous souhaitez utiliser plusieurs groupes, terrain, 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"
7
répondu Peter 2014-05-18 14:34:33

étant terminologique, [[ opérateur extrait l'élément d'une liste alors que [ opérateur prend sous-ensemble d'une liste.

6
répondu submartingale 2017-08-06 21:54:41

, Veuillez consulter ci-dessous une explication détaillée.

j'ai utilisé la base 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 de la table s'appelle l'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 des données réelles. Chaque membre de données d'une ligne s'appelle une cellule.

unique " crochets "[]" de l'opérateur

pour récupérer des données dans une cellule, nous entrerions ses coordonnées de ligne et de colonne dans l'opérateur simple crochet" []". Les deux coordonnées sont séparés par une virgule. En d'autres termes, les coordonnées commencent par la position de la rangée, puis sont suivies d'une virgule, et se terminent par la position de la colonne. L'ordre est important.

Eg 1:- Ici est la valeur de la cellule de la première ligne, deuxième colonne de mtcars.

> mtcars[1, 2] 
[1] 6

Eg 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 

double bracket carré "[[]] "operator

nous référons à une colonne de base de données avec l'opérateur double crochet" [[]".

Eg 1:-pour récupérer le vecteur de la neuvième colonne du jeu de données intégré mtcars, nous écrivons mtcars[[9]].

mtcars [[9]] [1] 1 1 1 0 0 0 0 0 0 0 0 ...

Eg 2: - nous pouvons récupérer le même vecteur de colonne par son nom.

mtcars[["suis"]] [1] 1 1 1 0 0 0 0 0 0 0 0 ...

-1
répondu Prasan Karunarathne 2018-09-05 20:24:16