Safely get or set an element deep within a nested data structureSource:
pluck() implements a generalised form of
[[ that allow you to index
deeply and flexibly into data structures. It always succeeds, returning
.default if the index you are trying to access does not exist or is
pluck<-() is the assignment equivalent, allowing you to modify an object
deep within a nested data structure.
pluck_exists() tells you whether or not an object exists using the
same rules as pluck (i.e. a
NULL element is equivalent to an absent
- .x, x
A vector or environment
A list of accessors for indexing into the object. Can be an positive integer, a negative integer (to index from the right), a string (to index into names), 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.
Dynamic dots are supported. In particular, if your accessors are stored in a list, you can splice that in with
Value to use if target is
A value to replace in
.xat the pluck location. Use
zap()to instead remove the element.
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:
pluck(x, 1, accessor, "foo").
These accessors never partial-match. This is unlike
$which will select the
dispobject if you write
# Let's create a list of data structures: obj1 <- list("a", list(1, elt = "foo")) obj2 <- list("b", list(2, elt = "bar")) x <- list(obj1, obj2) # pluck() provides a way of retrieving objects from such data # structures using a combination of numeric positions, vector or # list names, and accessor functions. # Numeric positions index into the list by position, just like `[[`: pluck(x, 1) #> [] #>  "a" #> #> [] #> [][] #>  1 #> #> []$elt #>  "foo" #> #> # same as x[] # Index from the back pluck(x, -1) #> [] #>  "b" #> #> [] #> [][] #>  2 #> #> []$elt #>  "bar" #> #> # same as x[] pluck(x, 1, 2) #> [] #>  1 #> #> $elt #>  "foo" #> # same as x[][] # Supply names to index into named vectors: pluck(x, 1, 2, "elt") #>  "foo" # same as x[][][["elt"]] # By default, pluck() consistently returns `NULL` when an element # does not exist: pluck(x, 10) #> NULL try(x[]) #> Error in x[] : subscript out of bounds # You can also supply a default value for non-existing elements: pluck(x, 10, .default = NA) #>  NA # The map() functions use pluck() by default to retrieve multiple # values from a list: map_chr(x, 1) #>  "a" "b" map_int(x, c(2, 1)) #>  1 2 # pluck() also supports accessor functions: my_element <- function(x) x[]$elt pluck(x, 1, my_element) #>  "foo" pluck(x, 2, my_element) #>  "bar" # 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[]) #>  "foo" # If you have a list of accessors, you can splice those in with `!!!`: idx <- list(1, my_element) pluck(x, !!!idx) #>  "foo"