在mutate中使用purrr::pmap传递参数的问题及优化需求
问题解答
1. 给pmap中的函数正确传递参数的方法
报错原因解析
- sum能正常运行的逻辑:
sum()支持接收任意数量的位置参数(sum(a, b, c, ...)),pmap会把数据框每行的多列值拆成独立参数传给sum,再配合na.rm=TRUE这个命名参数,自然能算出每行总和。 - mean报错的核心原因:
mean()的第一个参数x要求是一个向量,但pmap默认会把每行的多列值拆成多个位置参数传入,相当于执行mean(col_a_val, col_b_val, col_c_val, na.rm=TRUE),这不符合mean的参数规则(它仅将第一个参数视为目标向量,后续参数对应trim等其他参数),因此触发"argument 'x' is missing"错误。 - 直接传
sum(na.rm=TRUE)报错的原因:你这里是直接执行了sum(na.rm=TRUE),但sum必须要有输入值(x参数),这行代码本身就不合法,pmap拿到错误结果后自然无法执行。
正确写法
要让mean正常工作,需要把每行的多列值打包成一个向量再传入,可通过匿名函数结合...收集参数实现:
# 正确计算行均值 sdf_2 <- sdf %>% select(all_of(params)) %>% mutate(mean_p = pmap_dbl(., ~mean(c(...), na.rm = TRUE)))
如果要给sum显式传参(不依赖它的多参数特性),同样可以用匿名函数:
# 显式打包参数的行总和写法 sdf_2 <- sdf %>% select(all_of(params)) %>% mutate(sum_p = pmap_dbl(., ~sum(c(...), na.rm = TRUE)))
也可以用purrr::lift_dbl把接受向量的函数转换成支持多参数的版本,省去匿名函数的编写:
library(purrr) # 用lift_dbl转换mean函数 sdf_2 <- sdf %>% select(all_of(params)) %>% mutate(mean_p = pmap_dbl(., lift_dbl(mean, na.rm = TRUE)))
2. 保留col_id列同时处理指定列的方法
不需要先删除col_id再重建,用dplyr::pick()就能在pmap中直接指定要处理的列,同时保留原数据框的所有列:
# 保留col_id,同时计算指定列的行总和与均值 sdf_2 <- sdf %>% mutate( sum_p = pmap_dbl(pick(all_of(params)), ~sum(c(...), na.rm = TRUE)), mean_p = pmap_dbl(pick(all_of(params)), ~mean(c(...), na.rm = TRUE)) )
更简洁的方式是用rowwise()结合c_across(),这是dplyr中按行处理指定列的常用写法,可读性更高:
sdf_2 <- sdf %>% rowwise() %>% mutate( sum_p = sum(c_across(all_of(params)), na.rm = TRUE), mean_p = mean(c_across(all_of(params)), na.rm = TRUE) ) %>% ungroup()
内容的提问来源于stack exchange,提问作者Radek Jaźwiec
相关产品推荐
相关产品推荐

