當前位置: 首頁>>代碼示例 >>用法及示例精選 >>正文


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。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。