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