使用`purrr::map`与组合函数。

3
我希望您能够翻译关于编程的中文内容。需要使用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第一个元素:
# 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"

我该如何做到这一点?


2
map(x, ~ first(class(.x))) 行不行? - akrun
2
或者使用compose:purrr::map(x, purrr::compose(first, class))purrr::map(x, purrr::compose(~.[[1]], class))。你不能从组合外部向组合内的不同部分传递不同的参数。 - MrFlick
@akrun,太好了!如果我非常想使用[[,那么purrr::map(x, ~class(.x)[[1]])也可以。你能发布你的答案吗?我会接受它。 - Indrajeet Patil
3个回答

5
如果我们使用波浪符~,只需要将first包裹起来即可得到预期的输出。
library(purrr)
map(x, ~ first(class(.)))

.x 不需要 x - Rui Barradas
@RuiBarradas。抱歉,我没有理解你的评论。这里的“x”是一个“列表”对象。 - akrun
map(x, ~ first(class(.))) gave me the same output as map(x, ~ first(class(.x))) - Rui Barradas
2
@RuiBarradas。是的,这是真的,在?map中它说:对于单参数函数,请使用.。它可以是..x。当map2中有两个参数时,.x变得相关。我不想改变mapmap2中的参数,所以使用了.x - akrun
2
@RuiBarradas: 我发现在~ lambda函数内最好使用.x,因为它可以与magrittr管道%>%中使用的.区分开来。考虑使用mtcars %>% map_at( ncol(.), ~.x*100 )。这样写使之立即显而易见哪个代词与管道相关,哪个代词与lambda函数相关。 - Artem Sokolov

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日创建的


0

来自 ?compose

compose(..., .dir = c("backward", "forward"))

... 函数按顺序应用(默认情况下从右到左)等等...

.dir 如果为“backward”(默认值),则按照数学中的惯例,函数将以相反的顺序从右到左调用。如果为“forward”,则从左到右调用。

因此,我们只需要反转函数顺序。此外,compose 不知道 i=1L 属于哪个函数,因此 compose 将其附加到最后一个函数,即 class,因此我们需要将 i=1L 明确定义为所需的函数。

purrr::map(.x = x, .f = purrr::compose(~.x[[1]], class))
[[1]]
[1] "data.frame"

[[2]]
[1] "tbl_df"

[[3]]
[1] "character"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接