Het verschil tussen haak [ ] en dubbele haak [[ ]] voor toegang tot de elementen van een lijst of dataframe

Rbiedt twee verschillende methoden voor toegang tot de elementen van een lijst of data.frame: []en [[]].

Wat is het verschil tussen de twee en wanneer moet ik de een boven de ander gebruiken?


Antwoord 1, autoriteit 100%

De R-taaldefinitie is handig voor het beantwoorden van dit soort vragen:

R heeft drie basisoperatoren voor indexeren, waarvan de syntaxis wordt weergegeven in de volgende voorbeelden:

   x[i]
    x[i, j]
    x[[i]]
    x[[i, j]]
    x$a
    x$"a"

Voor vectoren en matrices worden de [[-vormen zelden gebruikt, hoewel ze enkele kleine semantische verschillen hebben met de [-vorm (bijv. matching wordt gebruikt voor karakterindices). Bij het indexeren van multidimensionale structuren met een enkele index, retourneert x[[i]]of x[i]het ide opeenvolgende element van x.

Voor lijsten gebruikt men over het algemeen [[>om een enkel element te selecteren, terwijl [een lijst van de geselecteerde elementen teruggeeft.

Met de [[-vorm kan slechts één enkel element worden geselecteerd met behulp van integer- of tekenindices, terwijl [indexering door vectoren toestaat. Merk echter op dat voor een lijst de index een vector kan zijn en dat elk element van de vector op zijn beurt wordt toegepast op de lijst, de geselecteerde component, de geselecteerde component van die component, enzovoort. Het resultaat is nog steeds een enkel element.


Antwoord 2, autoriteit 52%

De significante verschillen tussen de twee methoden zijn de klasse van de objecten die ze retourneren wanneer ze worden gebruikt voor extractie en of ze een reeks waarden accepteren, of slechts een enkele waarde tijdens de toewijzing.

Beschouw het geval van gegevensextractie op de volgende lijst:

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

Stel dat we de waarde die door bool is opgeslagen uit foo willen extraheren en gebruiken in een if()-statement. Dit illustreert de verschillen tussen de retourwaarden van []en [[]]wanneer ze worden gebruikt voor gegevensextractie. De methode []retourneert objecten uit de klassenlijst (of data.frame als foo een data.frame was), terwijl de methode [[]]objecten retourneert waarvan de klasse wordt bepaald door het type van hun waarden.

Dus het gebruik van de []methode resulteert in het volgende:

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

Dit komt omdat de methode []een lijst retourneerde en een lijst geen geldig object is om rechtstreeks door te geven aan een if()-instructie. In dit geval moeten we [[]]gebruiken omdat het het “bare” object teruggeeft dat is opgeslagen in ‘bool’ en dat de juiste klasse zal hebben:

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

Het tweede verschil is dat de operator []kan worden gebruikt om toegang te krijgen tot een bereikvan slots in een lijst of kolommen in een dataframe, terwijl de [[]]operator is beperkt tot toegang tot een enkeleslot of kolom. Overweeg het geval van waardetoewijzing met behulp van een tweede lijst, bar():

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

Stel dat we de laatste twee slots van foo willen overschrijven met de gegevens in bar. Als we de operator [[]]proberen te gebruiken, gebeurt dit:

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

Dit komt omdat [[]]beperkt is tot toegang tot een enkel element. We moeten []gebruiken:

foo[ 2:3 ] <- bar
print( foo )
$str
[1] "R"
$vec
     [,1] [,2]
[1,]    0    0
[2,]    0    0
$bool
[1] -0.6291121

Houd er rekening mee dat hoewel de toewijzing succesvol was, de slots in foo hun oorspronkelijke namen hebben behouden.


Antwoord 3, autoriteit 35%

Dubbele haakjes geeft toegang tot een lijst element, terwijl een enkel haakje je een lijst teruggeeft met een enkel element.

lst <- list('one','two','three')
a <- lst[1]
class(a)
## returns "list"
a <- lst[[1]]
class(a)
## returns "character"

Antwoord 4, autoriteit 26%

Van Hadley Wickham:

Van Hadley Wickham

Mijn (slecht uitziende) wijziging om te laten zien met behulp van propereverse / purrr:

voer hier de afbeeldingsbeschrijving in


Antwoord 5, autoriteit 15%

[]extraheert een lijst, [[]]extraheert elementen binnen de lijst

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"

Antwoord 6, autoriteit 6%

Hier even toevoegen dat [[ook is uitgerust voor recursieve indexering.

Hiernaar werd gesuggereerd in het antwoord van @JijoMatthew, maar niet onderzocht.

Zoals vermeld in ?"[[", syntaxis zoals x[[y]], waarbij length(y) > 1, wordt geïnterpreteerd als:

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

Merk op dat dit nietsverandert wat uw belangrijkste afhaalpunt zou moeten zijn over het verschil tussen [en [[] — namelijk dat de eerste wordt gebruikt voor subsettingen de laatste wordt gebruikt voor het extraherenenkele lijstelementen.

Bijvoorbeeld

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

Om de waarde 3 te krijgen, kunnen we het volgende doen:

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

Om terug te komen op het antwoord van @JijoMatthew hierboven, onthoud r:

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

Dit verklaart met name de fouten die we vaak krijgen bij verkeerd gebruik van [[, namelijk:

r[[1:3]]

Fout in r[[1:3]]: recursieve indexering mislukt op niveau 2

Aangezien deze code daadwerkelijk probeerde r[[1]][[2]][[3]]te evalueren, en het nesten van rstopt op niveau één , de poging om via recursieve indexering te extraheren is mislukt op [[2]], dwz op niveau 2.

Fout in r[[c("foo", "far")]]: subscript buiten de grenzen

Hier was R op zoek naar r[["foo"]][["far"]], die niet bestaat, dus we krijgen de subscript-fout.

p>

Het zou waarschijnlijk wat handiger/consistenter zijn als beide fouten hetzelfde bericht zouden geven.


Antwoord 7, autoriteit 5%

Omdat het terminologisch is, neemt de [[operator extraheerthet element uit een lijst, terwijl de [operator subsetvan een lijst.


Antwoord 8, autoriteit 4%

Om nieuwkomers te helpen door de handmatige mist te navigeren, kan het handig zijn om de notatie [[ ... ]]te zien als een instortende-functie – met andere woorden, het is wanneer u gewoon ‘de gegevens wilt ophalen’ van een benoemde vector, lijst of gegevensframe. Het is goed om dit te doen als u gegevens uit deze objecten wilt gebruiken voor berekeningen. Deze eenvoudige voorbeelden zullen dit illustreren.

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

Dus uit het derde voorbeeld:

> 2 * x[1]
  x
1 2
> 2 * x[[1]]
[1] 2

Antwoord 9, autoriteit 2%

Voor nog een ander concreet gebruiksgeval, gebruik dubbele haakjes als je een dataframe wilt selecteren dat is gemaakt met de functie split(). Als je het niet weet, groepeert split()een lijst/dataframe in subsets op basis van een sleutelveld. Het is handig als u met meerdere groepen wilt werken, ze wilt plotten, enz.

> 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"

Antwoord 10

Raadpleeg de onderstaande gedetailleerde uitleg.

Ik heb een ingebouwd dataframe in R gebruikt, mtcars genaamd.

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

De bovenste regel van de tabel wordt de kop genoemd die de kolomnamen bevat. Elke horizontale lijn daarna geeft een gegevensrij aan, die begint met de naam van de rij en vervolgens wordt gevolgd door de feitelijke gegevens.
Elk gegevenslid van een rij wordt een cel genoemd.

enkele vierkante haak “[]” operator

Om gegevens in een cel op te halen, voeren we de rij- en kolomcoördinaten in tussen de enkele vierkante haak “[]”-operator. De twee coördinaten worden gescheiden door een komma. Met andere woorden, de coördinaten beginnen met rijpositie, gevolgd door een komma en eindigen met de kolompositie. De volgorde is belangrijk.

Bijv. 1:- Hier is de celwaarde van de eerste rij, tweede kolom van mtcars.

> mtcars[1, 2] 
[1] 6

Bijvoorbeeld 2:- Verder kunnen we de rij- en kolomnamen gebruiken in plaats van de numerieke coördinaten.

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

Dubbele vierkante haak “[[]]” operator

We verwijzen naar een dataframekolom met de dubbele vierkante haak “[[]]”-operator.

Bijv. 1:- Om de negende kolomvector van de ingebouwde dataset mtcars op te halen, schrijven we mtcars[[9]].

mtcars[[9]]
[1] 1 1 1 0 0 0 0 0 0 0 0 …

Bijv. 2:- We kunnen dezelfde kolomvector op naam ophalen.

mtcars[[“am”]]
[1] 1 1 1 0 0 0 0 0 0 0 0 …


Antwoord 11

Bovendien:

Volgens de LINKvan de ANTWOORDhier.

Hier is een klein voorbeeld waarin het volgende punt wordt behandeld:

x[i, j] vs x[[i, j]]

df1   <- data.frame(a = 1:3)
df1$b <- list(4:5, 6:7, 8:9)
df1[[1,2]]
df1[1,2]
str(df1[[1,2]])
str(df1[1,2])

Other episodes