Menu Home

R Tip: Use [[ ]] Wherever You Can

R tip: use [[ ]] wherever you can.

In R the [[ ]] is the operator that (when supplied a simple scalar argument) pulls a single element out of lists (and the [ ] operator pulls out sub-lists).

For vectors [[ ]] and [ ] appear to be synonyms (modulo the issue of names). However, for a vector [[ ]] checks that the indexing argument is a scalar, so if you intend to retrieve one element this is a good way of getting an extra check and documenting intent. Also, when writing reusable code you may not always be sure if your code is going to be applied to a vector or list in the future.

It is safer to get into the habit of always using [[ ]] when you intend to retrieve a single element.

Example with lists:

list("a", "b")[1]
#> [[1]]
#> [1] "a"

list("a", "b")[[1]]
#> [1] "a"

Example with vectors:

c("a", "b")[1]
#> [1] "a"

c("a", "b")[[1]]
#> [1] "a"

The idea is: in situations where both [ ] and [[ ]] apply we rarely see [[ ]] being the worse choice.

Note on this article series.

This R tips series is short simple notes on R best practices, and additional packaged tools. The intent is to show both how to perform common tasks, and how to avoid common pitfalls. I hope to share about 20 of these about every other day to learn from the community which issues resonate and to also introduce some of features from some of our packages. It is an opinionated series and will sometimes touch on coding style, and also try to showcase appropriate Win-Vector LLC R tools.

Categories: Administrativia Coding Tutorials

Tagged as:


Data Scientist and trainer at Win Vector LLC. One of the authors of Practical Data Science with R.

7 replies

  1. thanks and good work
    but please I need your help
    can you help me on opening OC-CCI products (.nc) format
    if you are willing let me know and let me send you the details

  2. This is a good tip. I call them “just in case” tips. As you correctly points out, it is a good idea to have [[]] if your object becomes a list in the future (data frames are list so it counts here). Another minor benefit from this practice is that it always reminds you the subtle differences between [] and [[]] across classes.

    1. I really like your point. I do get a lot of “I would never make that mistake” feedback on tips like these. What you said really sums up why one might care. Thanks!

  3. There’s one more important difference. Using [[]] will get the value and drop the name. IMO that’s very important sometimes, whether you want to retain only the value or not.

    foo <- c(“a” = 1, “b” = 2); print(foo[1]); print(foo[[1]])

  4. Cool thing I learned recently: [[row, col]] will work with arrays (including data.frames) and do the nice check that only one value is grabbed. For example, mtcars[[5, “cyl”]] works, but mtcars[[5:6, “cyl”]] is an error.

    Something similar works with lists, but they require a vector be provided: list(letters, LETTERS)[[c(2, 26)]] returns “Z”. But the indices need to be all integers or all characters; no mixing.

    1. That is new to me, thanks!

      The first one is entirely new to me (and a surprise).

      The second one I heard about right after putting this article out. list(1,1)[[c(1,1)]] is funny case.

%d bloggers like this: