# map_depth: Map/modify elements at given depth In purrr: Functional Programming Tools

 map_depth R Documentation

## Map/modify elements at given depth

### Description

`map_depth()` calls `map(.y, .f)` on all `.y` at the specified `.depth` in `.x`. `modify_depth()` calls `modify(.y, .f)` on `.y` at the specified `.depth` in `.x`.

### Usage

``````map_depth(.x, .depth, .f, ..., .ragged = .depth < 0, .is_node = NULL)

modify_depth(.x, .depth, .f, ..., .ragged = .depth < 0, .is_node = NULL)
``````

### Arguments

 `.x` A list or atomic vector. `.depth` Level of `.x` to map on. Use a negative value to count up from the lowest level of the list. `map_depth(x, 0, fun)` is equivalent to `fun(x)`. `map_depth(x, 1, fun)` is equivalent to `x <- map(x, fun)` `map_depth(x, 2, fun)` is equivalent to `⁠x <- map(x, \(y) map(y, fun))⁠` `.f` A function, specified in one of the following ways: A named function, e.g. `mean`. An anonymous function, e.g. `⁠\(x) x + 1⁠` or `function(x) x + 1`. A formula, e.g. `~ .x + 1`. You must use `.x` to refer to the first argument. Only recommended if you require backward compatibility with older versions of R. A string, integer, or list, e.g. `"idx"`, `1`, or `list("idx", 1)` which are shorthand for `⁠\(x) pluck(x, "idx")⁠`, `⁠\(x) pluck(x, 1)⁠`, and `⁠\(x) pluck(x, "idx", 1)⁠` respectively. Optionally supply `.default` to set a default value if the indexed element is `NULL` or does not exist. `...` Additional arguments passed on to the mapped function. We now generally recommend against using `...` to pass additional (constant) arguments to `.f`. Instead use a shorthand anonymous function: ```# Instead of x |> map(f, 1, 2, collapse = ",") # do: x |> map(\(x) f(x, 1, 2, collapse = ",")) ``` This makes it easier to understand which arguments belong to which function and will tend to yield better error messages. `.ragged` If `TRUE`, will apply to leaves, even if they're not at depth `.depth`. If `FALSE`, will throw an error if there are no elements at depth `.depth`. `.is_node` A predicate function that determines whether an element is a node (by returning `TRUE`) or a leaf (by returning `FALSE`). The default value, `NULL`, treats simple lists as nodes and everything else (including richer objects like data frames and linear models) as leaves, using `vctrs::vec_is_list()`. To recurse into all objects built on lists use `is.list()`.

### See Also

`modify_tree()` for a recursive version of `modify_depth()` that allows you to apply a function to every leaf or every node.

Other map variants: `imap()`, `lmap()`, `map2()`, `map_if()`, `map()`, `modify()`, `pmap()`

Other modify variants: `modify_tree()`, `modify()`

### Examples

``````# map_depth() -------------------------------------------------
# Use `map_depth()` to recursively traverse nested vectors and map
# a function at a certain depth:
x <- list(a = list(foo = 1:2, bar = 3:4), b = list(baz = 5:6))
x |> str()
x |> map_depth(2, \(y) paste(y, collapse = "/")) |> str()

# Equivalent to:
x |> map(\(y) map(y, \(z) paste(z, collapse = "/"))) |> str()

# When ragged is TRUE, `.f()` will also be passed leaves at depth < `.depth`
x <- list(1, list(1, list(1, list(1, 1))))
x |> str()
x |> map_depth(4, \(x) length(unlist(x)), .ragged = TRUE) |> str()
x |> map_depth(3, \(x) length(unlist(x)), .ragged = TRUE) |> str()
x |> map_depth(2, \(x) length(unlist(x)), .ragged = TRUE) |> str()
x |> map_depth(1, \(x) length(unlist(x)), .ragged = TRUE) |> str()
x |> map_depth(0, \(x) length(unlist(x)), .ragged = TRUE) |> str()

# modify_depth() -------------------------------------------------
l1 <- list(
obj1 = list(
prop1 = list(param1 = 1:2, param2 = 3:4),
prop2 = list(param1 = 5:6, param2 = 7:8)
),
obj2 = list(
prop1 = list(param1 = 9:10, param2 = 11:12),
prop2 = list(param1 = 12:14, param2 = 15:17)
)
)

# In the above list, "obj" is level 1, "prop" is level 2 and "param"
# is level 3. To apply sum() on all params, we map it at depth 3:
l1 |> modify_depth(3, sum) |> str()

# modify() lets us pluck the elements prop1/param2 in obj1 and obj2:
l1 |> modify(c("prop1", "param2")) |> str()

# But what if we want to pluck all param2 elements? Then we need to
# act at a lower level:
l1 |> modify_depth(2, "param2") |> str()

# modify_depth() can be with other purrr functions to make them operate at
# a lower level. Here we ask pmap() to map paste() simultaneously over all
# elements of the objects at the second level. paste() is effectively
# mapped at level 3.
l1 |> modify_depth(2, \(x) pmap(x, paste, sep = " / ")) |> str()
``````

purrr documentation built on Aug. 10, 2023, 9:08 a.m.