Using single vs double square brackets

Hello,
I am still slightly confused about the difference in output between single square brackets [ ] and double brackets [[ ]] to extract an element or column from a vector or dataframe. See the example below where we get kind of the same results but with single square brackets I get a column of numbers and with [[ ]] we get a horizontal list of numbers...

image

Does the single square bracket access only one element? What if we use two indices and single square brackets? When using the double square brackets, I get the same results so I am confused...I know that one outputs a list while the other does not...

Thanks for any clarification...

as a heuristic double square brackets will unbox/unwrap the result it gives you; i.e. you will get to the raw/naked element value from it; single square brackets will generally give you the result boxed/wrapped. either letting it have supplementary info like names attached; or as a list if it was pulled from a list, or a data.frame if it was in a data.frame or a tibble if it was in a tibble etc.

#The usual form of indexing is [. [[ can be used to select a single element dropping names, whereas [ keeps them, e.g
c(abc = 123)[1]
c(abc = 123)[[1]]

# give 1st element but return wrapped in a list
list(1,
     2)[1]
# give 1st element unwrapped; i.e. dont have the result in a list
list(1,
     2)[[1]]

data.frame(a=1)[1] # a data.frame
data.frame(a=1)[[1]]
tibble(a=1)[1]  # a tibble 
tibble(a=1)[[1]]
3 Likes

When in doubt, use str. If you get back a vector, it wants singles, and a list wants doubles. Or, heavens avert, lists of lists of lists \dots

1 Like

With analogy to pepper or train:
https://r4ds.had.co.nz/vectors.html?q=pepper#lists-of-condiments

https://twitter.com/hadleywickham/status/979388069362130944

https://adv-r.hadley.nz/subsetting.html

Or this:

1 Like

Thank you.

So, in general, if I have to extract a single element or multiple elements from a vector, would I use a single square bracket?

On the other end, to extract a single element or multiple elements (row or column )from a dataframe, would I use double square bracket?

Yes

xx <-  1:10
xx[5]

No, assuming I understand the question correctly

dat <- data.frame(xx =1:10, yy = letters[1:5])

dat[5, 1]

Worth some drills

# a vector
v <- c(LETTERS)
length(v)
#> [1] 26
str(v)
#>  chr [1:26] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" ...
v[1]
#> [1] "A"
str(v[1])
#>  chr "A"
# a data frame
d <- mtcars
nrow(d) # number of rows
#> [1] 32
length(d) # number of columns
#> [1] 11
# dimensions are row, column
dim(d)
#> [1] 32 11
# first column # car names are not a column
d[1]
#>                      mpg
#> Mazda RX4           21.0
#> Mazda RX4 Wag       21.0
#> Datsun 710          22.8
#> Hornet 4 Drive      21.4
#> Hornet Sportabout   18.7
#> Valiant             18.1
#> Duster 360          14.3
#> Merc 240D           24.4
#> Merc 230            22.8
#> Merc 280            19.2
#> Merc 280C           17.8
#> Merc 450SE          16.4
#> Merc 450SL          17.3
#> Merc 450SLC         15.2
#> Cadillac Fleetwood  10.4
#> Lincoln Continental 10.4
#> Chrysler Imperial   14.7
#> Fiat 128            32.4
#> Honda Civic         30.4
#> Toyota Corolla      33.9
#> Toyota Corona       21.5
#> Dodge Challenger    15.5
#> AMC Javelin         15.2
#> Camaro Z28          13.3
#> Pontiac Firebird    19.2
#> Fiat X1-9           27.3
#> Porsche 914-2       26.0
#> Lotus Europa        30.4
#> Ford Pantera L      15.8
#> Ferrari Dino        19.7
#> Maserati Bora       15.0
#> Volvo 142E          21.4
row.names(d) <- NULL
d[1]
#>     mpg
#> 1  21.0
#> 2  21.0
#> 3  22.8
#> 4  21.4
#> 5  18.7
#> 6  18.1
#> 7  14.3
#> 8  24.4
#> 9  22.8
#> 10 19.2
#> 11 17.8
#> 12 16.4
#> 13 17.3
#> 14 15.2
#> 15 10.4
#> 16 10.4
#> 17 14.7
#> 18 32.4
#> 19 30.4
#> 20 33.9
#> 21 21.5
#> 22 15.5
#> 23 15.2
#> 24 13.3
#> 25 19.2
#> 26 27.3
#> 27 26.0
#> 28 30.4
#> 29 15.8
#> 30 19.7
#> 31 15.0
#> 32 21.4
# first row, all columns
d[1,]
#>   mpg cyl disp  hp drat   wt  qsec vs am gear carb
#> 1  21   6  160 110  3.9 2.62 16.46  0  1    4    4
# second row, second columm
d[2,2]
#> [1] 6

# a list
l <- list(1,"a",2,"b")
length(l)
#> [1] 4
l[1]
#> [[1]]
#> [1] 1
str(l[1])
#> List of 1
#>  $ : num 1
l[2][[1]]
#> [1] "a"
# more checks
l[1][[1]] + l[2][[1]]
#> Error in l[1][[1]] + l[2][[1]]: non-numeric argument to binary operator
l[1][[1]] + l[3][[1]]
#> [1] 3

# some more tricks
l[sapply(l,is.numeric)] |> unlist()
#> [1] 1 2
d[sapply(d,function (x) x < 6)] |> head()
#> [1] 4 4 4 4 4 4
d[d[,2] < 6,] |> head()
#>     mpg cyl  disp hp drat    wt  qsec vs am gear carb
#> 3  22.8   4 108.0 93 3.85 2.320 18.61  1  1    4    1
#> 8  24.4   4 146.7 62 3.69 3.190 20.00  1  0    4    2
#> 9  22.8   4 140.8 95 3.92 3.150 22.90  1  0    4    2
#> 18 32.4   4  78.7 66 4.08 2.200 19.47  1  1    4    1
#> 19 30.4   4  75.7 52 4.93 1.615 18.52  1  1    4    2
#> 20 33.9   4  71.1 65 4.22 1.835 19.90  1  1    4    1
d[d[,2] < 6 & d$am > 0,] |> head()
#>     mpg cyl  disp hp drat    wt  qsec vs am gear carb
#> 3  22.8   4 108.0 93 3.85 2.320 18.61  1  1    4    1
#> 18 32.4   4  78.7 66 4.08 2.200 19.47  1  1    4    1
#> 19 30.4   4  75.7 52 4.93 1.615 18.52  1  1    4    2
#> 20 33.9   4  71.1 65 4.22 1.835 19.90  1  1    4    1
#> 26 27.3   4  79.0 66 4.08 1.935 18.90  1  1    4    1
#> 27 26.0   4 120.3 91 4.43 2.140 16.70  0  1    5    2

Created on 2023-01-20 with reprex v2.0.2

1 Like

This topic was automatically closed 42 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.