There are three subsetting operators in R ([[, [, and $) and they interact differently
with different data structures (atomic vector, list, data frame, etc.).
Here are a few reasons to prefer the [[ operator over [ or $ when you want to extract
an element from a data frame or a list:
Subsetting a list with [ always returns a smaller list, while [[ returns
the list element.
Subsetting a named atomic vector with [ returns a named vector, while [[ returns
the vector element.
Subsetting a data frame (but not tibble) with [ is type unstable; it can return
a vector or a data frame. [[, on the other hand, always returns a vector.
For a data frame (but not tibble), $ does partial matching (e.g. df$a will subset
df$abc), which can be a source of bugs. [[ doesn't do partial matching.
For data frames (and tibbles), irrespective of the size, the [[ operator is slower than $.
For lists, however, the reverse is true.