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?
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]]
lubx[i]
zwrócii
element sekwencyjnyx
.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.
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.
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"
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"
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
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.
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.
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
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
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"
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.
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 ...
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