如何在dplyr的mutate中从单函数返回多列并自定义列名?
解决dplyr中调用多列输出函数时自定义列名的问题
针对你遇到的调用abc函数后无法稳定自定义输出列名的问题,这里提供几种可行的方案:
方案一:用purrr::set_names配合!!!展开赋值
利用!!!操作符将命名后的列列表展开,让mutate直接识别为多列赋值,这是最直接的方式:
library(dplyr) library(purrr) # 示例数据 a = data.frame(a = 1:3, b = 4:6) # 原函数 abc = \(x) data.frame(x/2, x/3) # 自定义列名调用 a %>% mutate(!!!set_names(abc(a), c("a1", "a2")), !!!set_names(abc(b), c("b1", "b2")))
运行结果:
a b a1 a2 b1 b2 1 1 4 0.5 0.3333333 2.0 1.333333 2 2 5 1.0 0.6666667 2.5 1.666667 3 3 6 1.5 1.0000000 3.0 2.000000
方案二:给原函数加一个列名参数的包装函数
封装一个带列名参数的函数,让每次调用时直接指定列名,代码可读性更高:
library(dplyr) a = data.frame(a = 1:3, b = 4:6) abc = \(x) data.frame(x/2, x/3) # 包装函数,接受变量和目标列名 abc_named = \(x, col_names) setNames(abc(x), col_names) # 调用时直接传入列名 a %>% mutate(abc_named(a, c("a1", "a2")), abc_named(b, c("b1", "b2")))
此方案和方案一效果一致,适合需要频繁调用abc函数的场景,逻辑更清晰。
方案三:结合bind_cols与rename_with
如果不想使用!!!操作符,也可以通过bind_cols拼接命名后的结果:
library(dplyr) a = data.frame(a = 1:3, b = 4:6) abc = \(x) data.frame(x/2, x/3) a %>% bind_cols( # 对a的结果重命名 abc(.$a) %>% rename_with(~paste0("a", 1:2)), # 对b的结果重命名 abc(.$b) %>% rename_with(~paste0("b", 1:2)) )
为什么原语法不生效?
你尝试的c("a1","a2") := abc(a)无法生效,是因为dplyr的:=赋值语法中,左侧需要是单个列名,或是通过!!!展开的命名列表。直接传入字符向量时,mutate无法将其解析为多个列的赋值规则,而!!!可以把命名后的列表元素逐个映射为列名和对应值。
内容的提问来源于stack exchange,提问作者xiaodai
相关产品推荐
相关产品推荐

