将`purrr :: map`与组合功能一起使用

时间:2019-08-13 15:02:12

标签: r functional-programming tidyverse purrr

我想知道如何使用purrr::map,其中.f是两个不同功能的组合。

首先,让我们创建一个映射复合函数的列表:

library(tidyverse)

# create a list
x <- list(mtcars, tibble::as_tibble(iris), c("x", "y", "z"))

# extracting class of objects
purrr::map(.x = x, .f = class)
#> [[1]]
#> [1] "data.frame"
#> 
#> [[2]]
#> [1] "tbl_df"     "tbl"        "data.frame"
#> 
#> [[3]]
#> [1] "character"

现在让我们说我要提取列表中每个元素的class first 元素:

# this works but uses `map` twice
purrr::map(.x = x, .f = class) %>%
  purrr::map(.x = ., .f = `[[`, i = 1L)

#> [[1]]
#> [1] "data.frame"
#> 
#> [[2]]
#> [1] "tbl_df"
#> 
#> [[3]]
#> [1] "character"

那行得通,但是我想避免两次使用map,而是想组成一个可以在一个步骤中提取类及其第一个元素的函数。因此,我尝试编写这样的函数,但它与map

的配合效果不佳
# error

purrr::map(.x = x, .f = purrr::compose(class, `[[`, i = 1L))
#> Can't convert an integer vector to function

# no error but not the expected output

purrr::map(.x = x, .f = purrr::compose(class, `[[`), i = 1L)
#> [[1]]
#> [1] "numeric"
#> 
#> [[2]]
#> [1] "numeric"
#> 
#> [[3]]
#> [1] "character"

我该怎么做?

3 个答案:

答案 0 :(得分:5)

如果我们使用~,只需将first包装起来即可获得预期的输出结果

library(purrr)
map(x, ~ first(class(.)))

答案 1 :(得分:1)

我们可以不用公式语法直接使用compose()

library(tidyverse)

x <- list(mtcars, tibble::as_tibble(iris), c("x", "y", "z"))

map(x, compose(first, class))
#> [[1]]
#> [1] "data.frame"
#> 
#> [[2]]
#> [1] "tbl_df"
#> 
#> [[3]]
#> [1] "character"

reprex package (v2.0.0) 于 2021 年 6 月 30 日创建

答案 2 :(得分:0)

来自?compose

  

compose(...,.dir = c(“后退”,“前进”))

     

... 要按顺序应用的功能(默认情况下从右到左)等...

     

.dir 如果为“ backward”(默认值),则按照数学中的常规从右到左的相反顺序调用函数。如果是“ forward”,则从左到右调用它们。

所以我们只需要反转函数顺序。另外,compose不知道i=1L属于哪个函数,因此在这种情况下,compose会将它附加到最后一个函数class,因此我们需要定义{{1} }专门用于预期的功能。

i=1L