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 + 1
或function(x) x + 1
。 -
一个公式,例如
~ .x + 1
。您必须使用.x
来引用第一个参数。仅当您需要向后兼容旧版本的 R 时才推荐。 -
字符串、整数或列表,例如
"idx"
、1
或list("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 purrr map_dfr 返回数据帧的函数
- R purrr map_if 有条件地将函数应用于向量的每个元素
- R purrr map2 映射两个输入
- R purrr map 将函数应用于向量的每个元素
- R purrr modify_in 修改拔取位置
- R purrr modify_tree 递归修改列表
- R purrr modify 有选择地修改元素
- R purrr accumulate 累积向量缩减的中间结果
- R purrr imap 将函数应用于向量的每个元素及其索引
- R purrr list_transpose 转置列表
- R purrr as_vector 将列表强制转换为向量
- R purrr array-coercion 强制数组列出
- R purrr auto_browse 包装一个函数,以便在出错时自动 browser()
- R purrr pluck 安全地获取或设置嵌套数据结构深处的元素
- R purrr insistently 将函数转换为等待,然后在错误后重试
- R purrr list_simplify 将列表简化为原子或 S3 向量
- R purrr rerun 多次重新运行表达式
- R purrr quietly 包装一个函数来捕获副作用
- R purrr list_flatten 压平列表
- R purrr pmap 同时映射多个输入(“并行”)
- R purrr possibly 包装函数以返回值而不是错误
- R purrr head_while 查找全部满足谓词的头/尾。
- R purrr rbernoulli 从伯努利分布生成随机样本
- R purrr rate-helpers 创建延迟率设置
- R purrr keep_at 根据元素的名称/位置保留/丢弃元素
注:本文由纯净天空筛选整理自Hadley Wickham等大神的英文原创作品 Map/modify elements at given depth。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。