R语言使用purrr::pmap调用自定义函数的方法及常见问题解答
问题解答
1. 为什么不能直接传入v1、v2?
R遵循作用域规则查找变量:直接写v1时,会优先在wrap_vr函数内部搜索对应变量,找不到就到全局环境搜索。你的全局环境中只有df这一个tibble对象,没有独立存在的v1、v2变量,直接传入会触发「对象未找到」的报错。
补充优化说明:你函数里用了all_of(vr),这个语法本来就是适配字符串格式列名的,你完全可以只传列名字符串,不用传整个列向量,写法更简洁:wrap_vr(df, "v1", "title_1", "ylabel_1")即可正常运行,不需要写df$v1。
2. pmap报错的原因
报错由两个问题共同导致:
- 输入列表结构不符合pmap要求:pmap是并行迭代函数,要求输入列表内的每个元素长度要么等于迭代次数,要么等于1(会自动循环复用)。你直接把整个
df作为列表第一个元素,tibble的默认长度等于列数也就是4,pmap会判定你需要迭代4次;但列表第二个元素是长度为2的列表,既不等于1也不等于4,直接触发长度不匹配的报错。 - 函数调用参数不匹配:你写的
~wrap_vr(.x)只接收了第一个参数,但wrap_vr需要4个入参,就算列表结构正确也会因为参数缺失报错。
正确写法示例
如果需要迭代2次生成2张图,调整后的代码如下:
library(tidyverse) df <- tibble(cy = c('a', 'a', 'b', 'b'), date = c(1,2,1,2), v1 = c(1,2,3,1), v2 = c(5,3,2,1)) wrap_vr <- function(df, vr, tit, ylab){ ggplot(data = df, aes(date, all_of(vr))) + geom_line(color = "steelblue", size = 1) + labs(title = tit, y = ylab, x = "") + facet_wrap(~ cy) } # 构造符合要求的输入列表 list_1 <- list( rep(list(df), 2), # 每次迭代都复用同一个df,包成长度为2的列表匹配迭代次数 c("v1", "v2"), # 直接传列名字符串即可 c("title_1", "title_2"), c("ylabel_1", "ylabel_2") ) # 调用pmap,自动按位置匹配参数 plots <- pmap(list_1, wrap_vr) # 调用对应位置的图片即可查看 plots[[1]] plots[[2]]
如果坚持要传列向量,把列表第二个元素替换为list(df$v1, df$v2)即可,其余逻辑不变。
内容的提问来源于stack exchange,提问作者sbac
相关产品推荐
相关产品推荐

