You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何减少purrr::map中的参数冗余?

问题

map语句实用性很强,但输入经常存在不必要的冗余。比如下面的代码块里,必须重复列出已经从tibble中调用的变量,显得很繁琐。我希望能直接给匿名函数使用\()语法,有没有办法减少这种冗余?当然我可以用mutate完成下面的任务,这里只是用来演示需求。

library(tidyverse)

mtcars |>
  as_tibble() |>
  mutate(
    test = pmap_chr(
      .l = list(mpg,cyl),
      .f = \(mpg,cyl){ # 太冗余了!!!
        str_glue("{mpg}_{cyl}")
      }
    )
  )

PS:虽然~语法对我有帮助,但它已经不是最佳实践了。

PPS:这不算正式问题(涉及主观偏好),但你更倾向于在mutate里用map还是直接在列表上用map?我发现在mutate里用map更有条理,需要的准备工作也更少,但一直不确定这是不是好做法,我看到更多人是直接构建列表传入purrr::map。

解答

一、减少pmap匿名函数的冗余写法

有几种方法可以避免重复声明变量名,同时保留\()匿名函数的使用:

方法1:用...统一接收参数

直接用...指代所有传入的参数,配合str_glue_data自动解析参数名,不用重复写变量:

library(tidyverse)

mtcars |>
  as_tibble() |>
  mutate(
    test = pmap_chr(
      .l = list(mpg, cyl),
      .f = \(...) str_glue_data(list(...), "{mpg}_{cyl}")
    )
  )

方法2:用lift函数适配多参数场景

purrr::lift可以把普通多参数函数转换成接受列表的函数,刚好匹配pmap的输入逻辑:

mtcars |>
  as_tibble() |>
  mutate(
    test = pmap_chr(
      .l = list(mpg, cyl),
      .f = lift(str_glue, .n = 2)
    )
  )

.n = 2指定参数数量,确保str_glue正确接收两个变量。

方法3:用rowwise替代map(更贴合tidy风格)

如果只是行内变量拼接这类简单操作,用rowwise配合c_across更简洁,完全不需要map:

mtcars |>
  as_tibble() |>
  rowwise() |>
  mutate(test = str_glue("{c_across(c(mpg, cyl))}") |> str_replace(", ", "_")) |>
  ungroup()

二、mutate中用map vs 直接在列表上用map的选择

没有绝对的优劣,完全看场景和工作流:

  • mutate + map:适合和tidyverse的管道流结合,直接在数据框的处理链路中生成新列,无需额外构建列表,代码连贯性和可读性都很强,我个人在处理数据框内的行级计算时更常用这种方式,完全是合理的实践。
  • 直接在列表上用map:适合独立的列表处理任务,比如处理非数据框的列表结构,或者需要对列表做复杂预处理后再映射的场景,灵活性更高。

核心原则是代码清晰易读,符合你的工作习惯——在数据框的tidy操作中,mutate+map的写法完全是实用且合理的选择。

内容的提问来源于stack exchange,提问作者Aegis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 21:02:36