使用带有构成功能的`purrr :: map`

Ind*_*til 3 functional-programming r purrr tidyverse

我想知道如何使用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"
Run Code Online (Sandbox Code Playgroud)

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

# 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"
Run Code Online (Sandbox Code Playgroud)

那行得通,但是我想避免使用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"
Run Code Online (Sandbox Code Playgroud)

我怎样才能做到这一点?

akr*_*run 5

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

library(purrr)
map(x, ~ first(class(.)))
Run Code Online (Sandbox Code Playgroud)

  • @RuiBarradas。是的,这是真的,并且在“?map”中表示“对于单个参数函数使用”。它可以是“。”或“ .x”。当map2中有两个参数时,.x才有意义。我不想同时更改map和map2中的参数,所以使用了.x (2认同)
  • @RuiBarradas:我发现最好在~~ lambda函数中使用`.x`,因为它与magrittr管道'%&gt;%`中的`.`区别开来。考虑`mtcars%&gt;%map_at(ncol(。),〜.x * 100)`。通过这种方式编写,可以立即清楚地知道哪个代词与管道相关联以及哪个代名词与lambda函数相关联。 (2认同)