首页 > 解决方案 > R - `purrr::map()` 中的复合函数与管道函数

问题描述

我有以下列表:

my_list = list(alpha = list('hi'), 
               beta = list(1:4, 'how'), 
               gamma = list(TRUE, FALSE, 'are'))
str(my_list)

List of 3
 $ alpha:List of 1
  ..$ : chr "hi"
 $ beta :List of 2
  ..$ : int [1:4] 1 2 3 4
  ..$ : chr "how"
 $ gamma:List of 3
  ..$ : logi TRUE
  ..$ : logi FALSE
  ..$ : chr "are"

我想弄清楚每个 1 级元素中包含哪些数据类型。为此,我可以使用以下管道:

piped = map(my_list, ~map(., class) %>% unique %>% unlist)
str(piped)
List of 3
 $ alpha: chr "character"
 $ beta : chr [1:2] "integer" "character"
 $ gamma: chr [1:2] "logical" "character"

...按预期工作。但是当我尝试将调用嵌套到uniqueinsideunlist()时,我得到了一些不同的东西:

composite = map(my_list, ~map(., class) %>% unlist(unique(.)))
str(composite)
List of 3
 $ alpha: chr "character"
 $ beta : chr [1:2] "integer" "character"
 $ gamma: chr [1:3] "logical" "logical" "character"

有人可以帮我理解为什么这两种方法不等效吗?

标签: rdata-manipulationpurrr

解决方案


如果您使用匿名函数而不是点符号,则更容易看到正在发生的事情。

piped = map(my_list, ~map(., class) %>% unique %>% unlist)是相同的

piped = map(my_list, function (x) map(x, class) %>% unique %>% unlist)

然后管道将每个步骤的输出放在每个后续函数的第一个位置,所以它变成

piped = map(my_list, function (x) unique(map(x, class)) %>% unlist)进而

piped = map(my_list, function (x) unlist(unique(map(x, class))))

哪个结果是

str(piped)
List of 3
 $ alpha: chr "character"
 $ beta : chr [1:2] "integer" "character"
 $ gamma: chr [1:2] "logical" "character"

相似地composite = map(my_list, ~map(., class) %>% unlist(unique(.)))

可以写成

composite = map(my_list, function(x) map(x, class) %>% unlist(unique(x)))

x 在管道两侧的两种用途是事情变得奇怪的地方。我认为您期望管道将内部 map 调用的输出代替调用中的 x unique,但第二个 x 获取外部 map 函数的输出。相反,管道执行其默认操作并将内部映射调用的输出放置在unlist函数的第一个位置,如下所示

composite = map(my_list, function(x) unlist(map(x, class),unique(x)))

这给了你

str(composite)
List of 3
 $ alpha: chr "character"
 $ beta : chr [1:2] "integer" "character"
 $ gamma: chr [1:3] "logical" "logical" "character"

推荐阅读