pluck() and chuck() implement a generalised form of [[ that allow you to index deeply and flexibly into data structures. pluck() consistently returns NULL when an element does not exist, chuck() always throws an error in that case.

pluck(.x, ..., .default = NULL)

chuck(.x, ...)

pluck(.x, ...) <- value

Arguments

.x, x

A vector or environment

...

A list of accessors for indexing into the object. Can be an integer position, a string name, or an accessor function (except for the assignment variants which only support names and positions). If the object being indexed is an S4 object, accessing it by name will return the corresponding slot.

These dots support tidy dots features. In particular, if your accessors are stored in a list, you can splice that in with !!!.

.default

Value to use if target is empty or absent.

value

A value to replace in .x at the pluck location.

Details

  • You can pluck or chuck with standard accessors like integer positions and string names, and also accepts arbitrary accessor functions, i.e. functions that take an object and return some internal piece.

    This is often more readable than a mix of operators and accessors because it reads linearly and is free of syntactic cruft. Compare: accessor(x[[1]])$foo to pluck(x, 1, accessor, "foo").

  • These accessors never partial-match. This is unlike $ which will select the disp object if you write mtcars$di.

See also

attr_getter() for creating attribute getters suitable for use with pluck() and chuck(). modify_in() for applying a function to a pluck location.

Examples

# pluck() supports integer positions, string names, and functions. # Using functions, you can easily extend pluck(). Let's create a # list of data structures: obj1 <- list("a", list(1, elt = "foobar")) obj2 <- list("b", list(2, elt = "foobaz")) x <- list(obj1, obj2) # And now an accessor for these complex data structures: my_element <- function(x) x[[2]]$elt # The accessor can then be passed to pluck: pluck(x, 1, my_element)
#> [1] "foobar"
pluck(x, 2, my_element)
#> [1] "foobaz"
# Even for this simple data structure, this is more readable than # the alternative form because it requires you to read both from # right-to-left and from left-to-right in different parts of the # expression: my_element(x[[1]])
#> [1] "foobar"
# If you have a list of accessors, you can splice those in with `!!!`: idx <- list(1, my_element) pluck(x, !!!idx)
#> [1] "foobar"
# You can also assign a value in a pluck location with pluck<-: pluck(x, 2, 2, "elt") <- "quuux" x
#> [[1]] #> [[1]][[1]] #> [1] "a" #> #> [[1]][[2]] #> [[1]][[2]][[1]] #> [1] 1 #> #> [[1]][[2]]$elt #> [1] "foobar" #> #> #> #> [[2]] #> [[2]][[1]] #> [1] "b" #> #> [[2]][[2]] #> [[2]][[2]][[1]] #> [1] 2 #> #> [[2]][[2]]$elt #> [1] "quuux" #> #> #>
# This is a shortcut for the prefix function assign_in(): y <- assign_in(x, list(2, 2, "elt"), value = "QUUUX") y
#> [[1]] #> [[1]][[1]] #> [1] "a" #> #> [[1]][[2]] #> [[1]][[2]][[1]] #> [1] 1 #> #> [[1]][[2]]$elt #> [1] "foobar" #> #> #> #> [[2]] #> [[2]][[1]] #> [1] "b" #> #> [[2]][[2]] #> [[2]][[2]][[1]] #> [1] 2 #> #> [[2]][[2]]$elt #> [1] "QUUUX" #> #> #>