Map 语句非常棒,但它们的输入常常让人感觉不必要的冗余。例如,在下面的块中,必须重新列出我已经从
tibble
请求的变量似乎很愚蠢。简而言之,我希望我可以为匿名函数添加 \()
。有谁有办法减少冗余吗?当然,我可以使用 mutate
完成下面的任务,但我只是想展示我正在寻找的内容。
library(tidyverse)
mtcars |>
as_tibble() |>
mutate(
test = pmap_chr(
.l = list(mpg,cyl),
.f = \(mpg,cyl){ #Ahhhh! So redundant!!!
str_glue("{mpg}_{cyl}")
}
)
)
PS:“~”不再是最佳实践,尽管这对我有帮助。
PPS:这不是问题的正式部分,因为它是基于意见的,但是您是否更喜欢在
mutate
中使用地图与直接在列表上使用地图?我发现将它们与 mutate
一起使用可以更有组织性并且需要更少的设置,但我一直想知道这是否是一个好主意。我不经常看到人们只是设置列表并将其输入到purrr::map
正如评论中所指出的,我们实际上并不需要
pmap_*
,但为了回答这个问题,我们必须使用它。
然后我们可以使用
with(list(...) ..whatever..)
来避免重复论证。在此代码中,为了简洁起见,我们使用了点 (.),但如果我们使用 |> 或者 mutate
位于 group_by
中,则使用更详细的 pick(everything())
。
library(dplyr)
library(purrr)
library(stringr)
mtcars[1:3, 1:3] %>%
mutate(test = pmap(., ~ with(list(...), str_glue("{mpg}_{cyl}"))))
## mpg cyl disp test
## Mazda RX4 21.0 6 160 21_6
## Mazda RX4 Wag 21.0 6 160 21_6
## Datsun 710 22.8 4 108 22.8_4
如果可以使用
str_glue_data
我们可以稍微简化一下。
mtcars[1:3, 1:3] %>%
mutate(test = pmap(., ~ str_glue_data(list(...), "{mpg}_{cyl}")))
如果
paste
没问题,那么对于这个例子
mtcars[1:3, 1:3] %>%
mutate(test = pmap_chr(., paste, sep = "_"))
这是一个不同的示例,表明
with/list
也适用于其他情况:
dat <- data.frame(a = 11:13, b = 21:23, c = 0)
dat %>%
mutate(p.value = pmap_dbl(., ~ with(list(...), prop.test(a, b)$p.value)))
## a b c p.value
## 1 11 21 0 1.0000000
## 2 12 22 0 0.8311704
## 3 13 23 0 0.6766573