当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


R purrr map_depth 在给定深度映射/修改元素


map_depth().x 中指定的 .depth 处对所有 .y 调用 map(.y, .f)modify_depth().x 中指定的 .depth 处对 .y 调用 modify(.y, .f)

用法

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

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

参数

.x

列表或原子向量。

.depth

要映射的 .x 级别。使用负值从列表的最低级别开始计数。

  • map_depth(x, 0, fun) 等价于 fun(x)

  • map_depth(x, 1, fun) 等价于 x <- map(x, fun)

  • map_depth(x, 2, fun) 等价于 x <- map(x, \(y) map(y, fun))

.f

一个函数,通过以下方式之一指定:

  • 命名函数,例如mean

  • 匿名函数,例如\(x) x + 1function(x) x + 1

  • 一个公式,例如~ .x + 1 。您必须使用.x 来引用第一个参数。仅当您需要向后兼容旧版本的 R 时才推荐。

  • 字符串、整数或列表,例如"idx"1list("idx", 1) 分别是 \(x) pluck(x, "idx")\(x) pluck(x, 1)\(x) pluck(x, "idx", 1) 的简写。如果索引元素为 NULL 或不存在,则可以选择提供 .default 以设置默认值。

...

传递给映射函数的附加参数。

我们现在通常建议不要使用 ... 将附加(常量)参数传递给 .f 。相反,使用简写匿名函数:

# Instead of
x |> map(f, 1, 2, collapse = ",")
# do:
x |> map(\(x) f(x, 1, 2, collapse = ","))

这使得更容易理解哪些参数属于哪个函数,并且往往会产生更好的错误消息。

.ragged

如果 TRUE ,将应用于叶子,即使它们不在深度 .depth 。如果 FALSE ,如果深度 .depth 没有元素,将会抛出错误。

.is_node

一个谓词函数,用于确定元素是节点(通过返回 TRUE )还是叶(通过返回 FALSE )。默认值 NULL 使用 vctrs::vec_is_list() 将简单列表视为节点,将其他所有内容(包括 DataFrame 和线性模型等更丰富的对象)视为叶子。要递归到列表上构建的所有对象,请使用 is.list()

也可以看看

modify_tree()modify_depth() 的递归版本,允许您将函数应用于每个叶子或每个节点。

其他Map变体: imap()lmap()map2()map_if()map()modify()pmap()

其他修改变体:modify_tree()modify()

例子

# 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()
#> List of 2
#>  $ a:List of 2
#>   ..$ foo: int [1:2] 1 2
#>   ..$ bar: int [1:2] 3 4
#>  $ b:List of 1
#>   ..$ baz: int [1:2] 5 6
x |> map_depth(2, \(y) paste(y, collapse = "/")) |> str()
#> List of 2
#>  $ a:List of 2
#>   ..$ foo: chr "1/2"
#>   ..$ bar: chr "3/4"
#>  $ b:List of 1
#>   ..$ baz: chr "5/6"

# Equivalent to:
x |> map(\(y) map(y, \(z) paste(z, collapse = "/"))) |> str()
#> List of 2
#>  $ a:List of 2
#>   ..$ foo: chr "1/2"
#>   ..$ bar: chr "3/4"
#>  $ b:List of 1
#>   ..$ baz: chr "5/6"

# 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()
#> List of 2
#>  $ : num 1
#>  $ :List of 2
#>   ..$ : num 1
#>   ..$ :List of 2
#>   .. ..$ : num 1
#>   .. ..$ :List of 2
#>   .. .. ..$ : num 1
#>   .. .. ..$ : num 1
x |> map_depth(4, \(x) length(unlist(x)), .ragged = TRUE) |> str()
#> List of 2
#>  $ :List of 1
#>   ..$ : int 1
#>  $ :List of 2
#>   ..$ :List of 1
#>   .. ..$ : int 1
#>   ..$ :List of 2
#>   .. ..$ :List of 1
#>   .. .. ..$ : int 1
#>   .. ..$ :List of 2
#>   .. .. ..$ : int 1
#>   .. .. ..$ : int 1
x |> map_depth(3, \(x) length(unlist(x)), .ragged = TRUE) |> str()
#> List of 2
#>  $ :List of 1
#>   ..$ : int 1
#>  $ :List of 2
#>   ..$ :List of 1
#>   .. ..$ : int 1
#>   ..$ :List of 2
#>   .. ..$ : int 1
#>   .. ..$ : int 2
x |> map_depth(2, \(x) length(unlist(x)), .ragged = TRUE) |> str()
#> List of 2
#>  $ :List of 1
#>   ..$ : int 1
#>  $ :List of 2
#>   ..$ : int 1
#>   ..$ : int 3
x |> map_depth(1, \(x) length(unlist(x)), .ragged = TRUE) |> str()
#> List of 2
#>  $ : int 1
#>  $ : int 4
x |> map_depth(0, \(x) length(unlist(x)), .ragged = TRUE) |> str()
#>  int 5

# 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()
#> List of 2
#>  $ obj1:List of 2
#>   ..$ prop1:List of 2
#>   .. ..$ param1: int 3
#>   .. ..$ param2: int 7
#>   ..$ prop2:List of 2
#>   .. ..$ param1: int 11
#>   .. ..$ param2: int 15
#>  $ obj2:List of 2
#>   ..$ prop1:List of 2
#>   .. ..$ param1: int 19
#>   .. ..$ param2: int 23
#>   ..$ prop2:List of 2
#>   .. ..$ param1: int 39
#>   .. ..$ param2: int 48

# modify() lets us pluck the elements prop1/param2 in obj1 and obj2:
l1 |> modify(c("prop1", "param2")) |> str()
#> List of 2
#>  $ obj1: int [1:2] 3 4
#>  $ obj2: int [1:2] 11 12

# 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()
#> List of 2
#>  $ obj1:List of 2
#>   ..$ prop1: int [1:2] 3 4
#>   ..$ prop2: int [1:2] 7 8
#>  $ obj2:List of 2
#>   ..$ prop1: int [1:2] 11 12
#>   ..$ prop2: int [1:3] 15 16 17

# 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()
#> List of 2
#>  $ obj1:List of 2
#>   ..$ prop1:List of 2
#>   .. ..$ : chr "1 / 3"
#>   .. ..$ : chr "2 / 4"
#>   ..$ prop2:List of 2
#>   .. ..$ : chr "5 / 7"
#>   .. ..$ : chr "6 / 8"
#>  $ obj2:List of 2
#>   ..$ prop1:List of 2
#>   .. ..$ : chr "9 / 11"
#>   .. ..$ : chr "10 / 12"
#>   ..$ prop2:List of 3
#>   .. ..$ : chr "12 / 15"
#>   .. ..$ : chr "13 / 16"
#>   .. ..$ : chr "14 / 17"
源代码:R/map-depth.R

相关用法


注:本文由纯净天空筛选整理自Hadley Wickham等大神的英文原创作品 Map/modify elements at given depth。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。