使用purrr::map_dfr时以参数值而非序号作为.id列取值的方案
常用的tidyverse风格实现方案有以下几种:
1. 优化现有写法:用purrr::set_names()替代基础setNames()
这是对你现有写法的最小改动优化,set_names()是purrr专为管道场景设计的函数,默认无参调用时会直接用元素自身的值作为列表名,语义更清晰,也是tidyverse用户的惯用写法:
library(tidyverse) list(2,4,6) %>% set_names() %>% map_dfr(~tibble(x=mean(mtcars$mpg^.)), .id="name")
2. 适配返回tibble的场景:映射后追加字段
针对你提到的「映射函数本身已经返回tibble,不想额外嵌套tibble()」的需求,直接在映射函数返回结果后加一行mutate()追加id字段即可,不需要依赖.id参数:
list(2,4,6) %>% map_dfr(~tibble(x=mean(mtcars$mpg^.)) %>% mutate(name = .))
对应broom拟合的场景写法更简洁,不需要修改原有映射逻辑:
list(2, 4, 6) %>% map_dfr(~ broom::tidy(lm(mpg~cyl, data=mtcars, offset=rep(., nrow(mtcars)))) %>% mutate(name = .))
3. 高扩展性写法:参数结构化后逐行计算
如果逻辑复杂、后续需要扩展参数,更符合tidyverse范式的写法是先把参数存为数据框,用rowwise逐行计算:
tibble(power = c(2,4,6)) %>% rowwise() %>% reframe( name = power, x = mean(mtcars$mpg^power) )
对应broom拟合场景:
tibble(power = c(2,4,6)) %>% rowwise() %>% reframe( name = power, broom::tidy(lm(mpg~cyl, data=mtcars, offset=rep(power, nrow(mtcars)))) )
这种写法的扩展性最好,新增参数、调整计算逻辑都不需要改动整体结构。
内容的提问来源于stack exchange,提问作者Ben Bolker
相关产品推荐
相关产品推荐

