Różnica między wspornikiem [] a wspornikiem podwójnym [[]] dla dostępu do elementów listy lub ramki danych

R udostępnia dwie różne metody dostępu do elementów listy lub danych.frame-operatory [] i [[]].

Jaka jest różnica między nimi? W jakich sytuacjach powinienem używać jednego nad drugim?

Author: Gregor, 2009-07-23

11 answers

Definicja języka R jest przydatna do odpowiedzi na tego typu pytania:

R ma trzy podstawowe operatory indeksujące, których składnia jest wyświetlana w następujących przykładach

{[0]}

Dla wektorów i macierzy formy [[ są rzadko używane, choć mają pewne niewielkie różnice semantyczne w stosunku do formy [ (np., i że częściowe dopasowanie jest używane dla indeksów znaków). Podczas indeksowania wielowymiarowych struktur za pomocą pojedynczego indeksu, x[[i]] lub x[i] zwróci i element sekwencyjny x.

W przypadku list zazwyczaj używa się [[, aby wybrać dowolny pojedynczy element, podczas gdy [ zwraca listę wybranych elementów.

Forma [[ umożliwia wybranie tylko jednego elementu za pomocą indeksów całkowitych lub znakowych, podczas gdy [ umożliwia indeksowanie za pomocą wektorów. Zauważ jednak, że dla lista, indeks może być wektorem i każdy element wektora jest stosowany kolejno do listy, wybranego składnika, wybranego składnika tego składnika i tak dalej. Wynik jest nadal jednym elementem.

 270
Author: ars,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-21 13:41:06

Znaczącymi różnicami między tymi dwoma metodami są Klasa obiektów, które zwracają, gdy są używane do ekstrakcji i czy mogą przyjmować zakres wartości, czy tylko jedną wartość podczas przypisywania.

Rozważ przypadek ekstrakcji danych na poniższej liście:

foo <- list( str='R', vec=c(1,2,3), bool=TRUE )

Powiedzmy, że chcemy wyodrębnić wartość przechowywaną przez bool z foo i użyć jej wewnątrz if() instrukcji. Zobrazuje to różnice między wartościami zwrotnymi [] i [[]], gdy są one wykorzystywane do ekstrakcji danych. Metoda [] zwraca obiekty klasy list (lub data.frame if foo was a data.frame), podczas gdy metoda [[]] zwraca obiekty, których klasa jest określona przez typ ich wartości.

Zatem użycie metody [] daje następujące rezultaty:

if( foo[ 'bool' ] ){ print("Hi!") }
Error in if (foo["bool"]) { : argument is not interpretable as logical

class( foo[ 'bool' ] )
[1] "list"

Dzieje się tak dlatego, że metoda [] zwraca listę, a lista nie jest prawidłowym obiektem do przekazania bezpośrednio do instrukcji if(). W tym przypadku musimy użyć [[]], ponieważ zwróci " bare" obiekt przechowywany w 'bool', który będzie miał odpowiednią klasę:

if( foo[[ 'bool' ]] ){ print("Hi!") }
[1] "Hi!"

class( foo[[ 'bool' ]] )
[1] "logical"

Druga różnica polega na tym, że operator [] może być użyty do uzyskania dostępu do zakresu slotów na liście lub kolumnach w ramce danych, podczas gdy operator [[]] jest ograniczony do dostępu do pojedynczego slotu lub kolumny . Rozważmy przypadek przypisania wartości używając drugiej listy, bar():

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

Powiedzmy, że chcemy nadpisać dwa ostatnie sloty foo danymi zawartymi w pasku. Jeśli spróbujemy użyć [[]] operator, tak się dzieje:

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

Dzieje się tak dlatego, że [[]] ogranicza się do dostępu do pojedynczego elementu. Musimy użyć []:

foo[ 2:3 ] <- bar
print( foo )

$str
[1] "R"

$vec
     [,1] [,2]
[1,]    0    0
[2,]    0    0

$bool
[1] -0.6291121

Zauważ, że podczas gdy zadanie się powiodło, automaty w foo zachowały swoje oryginalne nazwy.

 147
Author: Sharpie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-23 04:06:55

Podwójny nawias uzyskuje dostęp do listy element , podczas gdy pojedynczy nawias zwraca listę z pojedynczym elementem.

lst <- list('one','two','three')

a <- lst[1]
class(a)
## returns "list"

a <- lst[[1]]
class(a)
## returns "character"
 89
Author: medriscoll,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-03 20:18:22

[] wyciąga listę, [[]] wyciąga elementy z listy

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
Author: Brad Gilbert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-23 04:04:36

Od Hadley Wickham:

Od Hadley Wickham

Moja (gówniana) modyfikacja do pokazania za pomocą tidyverse/purrr:

Tutaj wpisz opis obrazka

 17
Author: jzadra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-14 22:54:11

Wystarczy dodać, że [[ jest również przystosowane do indeksowania rekurencyjnego.

To zostało zasugerowane w odpowiedzi przez @JijoMatthew, ale nie zbadane.

Jak zaznaczono w ?"[[", składnia podobna do x[[y]], gdzie length(y) > 1, jest interpretowana jako:

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

Zauważ, że to Nie zmienia tego, co powinno być twoim głównym wyjściem na różnicę między [ a [[ - mianowicie, że pierwsza jest używana do podzbioru , a druga jest używana do wyodrębnianie pojedynczych elementów listy.

Na przykład,

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

Aby otrzymać wartość 3, możemy wykonać:

x[[c(2, 1, 1, 1)]]
# [1] 3

Wracając do powyższej odpowiedzi @JijoMatthew, Przypomnij r:

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

W szczególności wyjaśnia to błędy, które zwykle otrzymujemy, gdy źle używamy [[, a mianowicie:

r[[1:3]]
W tym celu należy skontaktować się z inspektorem ochrony danych.]}

Ponieważ ten kod rzeczywiście próbował ocenić r[[1]][[2]][[3]], a zagnieżdżanie r zatrzymuje się na poziom pierwszy, próba wyodrębnienia poprzez indeksowanie rekurencyjne nie powiodła się na [[2]], tj. na poziomie 2.

Błąd w r[[c("foo", "far")]]: Indeks dolny poza granicami

Tutaj R szukał r[["foo"]][["far"]], który nie istnieje, więc uzyskujemy błąd indeksu dolnego poza granicami.

Prawdopodobnie byłoby nieco bardziej pomocne/spójne, gdyby oba te błędy dały ten sam komunikat.

 15
Author: MichaelChirico,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-30 20:43:24

Oba z nich są sposoby podzbiór. Pojedynczy nawias zwróci podzbiór listy, który sam w sobie będzie listą. ie: może zawierać lub nie może zawierać więcej niż jednego elementu. Z drugiej strony podwójny wspornik zwróci tylko jeden element z listy.

- pojedynczy nawias da nam listę. Możemy również użyć jednego nawiasu, jeśli chcemy zwrócić wiele elementów z listy. rozważ następującą listę: -

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

Teraz zwróć uwagę na sposób, w jaki lista jest zwrócony, gdy próbuję go wyświetlić. I wpisz r i naciśnij enter

>r

#the result is:-

[[1]]

 [1]  1  2  3  4  5  6  7  8  9 10

$foo

[1] 1

$far

[1] 2

Teraz zobaczymy magię pojedynczego nawiasu:-

>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

Co jest dokładnie takie samo jak wtedy, gdy próbowaliśmy wyświetlić wartość r na ekranie, co oznacza, że użycie pojedynczego nawiasu zwróciło listę, gdzie w indeksie 1 mamy wektor 10 elementów, wtedy mamy jeszcze dwa elementy o nazwach foo i far. Możemy również wybrać, aby dać pojedynczy indeks lub nazwę elementu jako wejście do pojedynczego / align = "left" / eg:

> r[1]

[[1]]

 [1]  1  2  3  4  5  6  7  8  9 10

W tym przykładzie daliśmy jeden indeks "1", a w zamian otrzymaliśmy listę z jednym elementem (który jest tablicą 10 liczb)

> r[2]

$foo

[1] 1

W powyższym przykładzie daliśmy jeden indeks " 2 " i w zamian otrzymaliśmy listę z jednym elementem

> r["foo"];

$foo

[1] 1

W tym przykładzie przekazaliśmy nazwę jednego elementu i w zamian zwrócono listę z jednym elementem.

Możesz również przekazać wektor nazw elementów takich jak:-

> x<-c("foo","far")

> r[x];

$foo

[1] 1

$far
[1] 2

W tym przykładzie minęliśmy wektor z dwie nazwy elementów " foo "i"far"

W zamian otrzymaliśmy listę z dwoma elementami.

W skrócie pojedynczy nawias zawsze zwróci ci inną listę z liczbą elementów równą liczbie elementów lub liczbie indeksów, które przekazujesz do pojedynczego nawiasu.

Natomiast podwójny wspornik zawsze zwróci tylko jeden element. Przed przejściem do podwójnego nawiasu należy pamiętać o notatce. 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.

Podam kilka przykładów. Proszę zachować zwróć uwagę na słowa pogrubione i wróć do nich po zakończeniu z poniższymi przykładami:

Podwójny wspornik zwróci rzeczywistą wartość indeksu.(To nie zwróci listę)

  > r[[1]]

     [1]  1  2  3  4  5  6  7  8  9 10


  >r[["foo"]]

    [1] 1

Dla podwójnych nawiasów jeśli spróbujemy wyświetlić więcej niż jeden element przechodząc wektor, spowoduje to błąd tylko dlatego, że nie został zbudowany w celu zaspokojenia tej potrzeby, ale po prostu zwrócić pojedynczy element.

Rozważ następujące

> 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
Author: Jijo Mathew,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-30 13:48:27

Aby pomóc początkującym w poruszaniu się po ręcznym mgle, pomocne może być zobacz notację [[ ... ]] jako funkcjęzwijającą się - innymi słowy, jest to sytuacja, gdy chcesz po prostu "pobrać dane" z nazwanego wektora, listy lub ramki danych. Dobrze jest to zrobić, jeśli chcemy wykorzystać dane z tych obiektów do obliczeń. Te proste przykłady ilustrują.

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

Więc z trzeciego przykładu:

> 2 * x[1]
  x
1 2
> 2 * x[[1]]
[1] 2
 12
Author: Redfoot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-18 14:33:09

Dla kolejnego konkretnego przypadku użycia, Użyj podwójnych nawiasów, gdy chcesz wybrać ramkę danych utworzoną przez funkcję split(). Jeśli nie wiesz, split() grupuje listę/ramkę danych w podzbiory na podstawie pola klucza. Jest to przydatne, jeśli chcesz operować na wielu grupach, wykreślić je itp.

> 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
Author: Peter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-18 14:34:33

Operator [[ wyciąga element z listy, podczas gdy operator [ przyjmuje podzbiór listy.

 6
Author: submartingale,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-06 21:54:41

Proszę zapoznać się z poniższym szczegółowym wyjaśnieniem.

Użyłem wbudowanej ramki danych w R, zwanej 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 ... 
           ............

Górna linia tabeli jest nazywana nagłówkiem zawierającym nazwy kolumn. Każda linia pozioma oznacza wiersz danych, który zaczyna się od nazwy wiersza, a następnie od rzeczywistych danych. Każdy element danych w wierszu nazywany jest komórką.

Pojedynczy wspornik kwadratowy "[]" operator

Aby odzyskać dane w komórce, wpisujemy jej wiersz oraz współrzędne kolumn w pojedynczym nawiasie kwadratowym operatora" []". Obie współrzędne są oddzielone przecinkiem. Innymi słowy, współrzędne zaczynają się od pozycji wiersza, a następnie przecinka i kończą się pozycją kolumny. Kolejność jest ważna.

Eg 1: - tutaj jest wartość komórki z pierwszego wiersza, drugiej kolumny mtcars.

> mtcars[1, 2] 
[1] 6

Eg 2: - Ponadto możemy używać nazw wierszy i kolumn zamiast współrzędnych numerycznych.

> mtcars["Mazda RX4", "cyl"] 
[1] 6 

Podwójny wspornik kwadratowy "[[]]" operator

Odwołujemy się do kolumny ramki danych z podwójnym nawiasem kwadratowym operatorem" [[]]".

Eg 1: - Aby pobrać wektor dziewiątej kolumny wbudowanego zestawu danych mtcars, zapisujemy mtcars [[9]].

Mtcars [[9]] [1] 1 1 1 0 0 0 0 0 0 0 0 ...

Eg 2: - możemy pobrać ten sam wektor kolumnowy po jego nazwie.

Mtcars [["am"]] [1] 1 1 1 0 0 0 0 0 0 0 0 ...

 -1
Author: Prasan Karunarathne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-05 20:24:16