如何用dplyr::mutate结合自定义列向量拼接生成新变量
问题
给定如下tibble数据框:
vehicles <- tibble(vehicle = c("Car", "Car", "Motorbike"), color = c("Red", "Black", "Blue"), speed = c("Low", "High", "High"))
对应的数据表:
| vehicle | color | speed |
|---|---|---|
| Car | Red | Low |
| Car | Black | High |
| Motorbike | Blue | High |
需要生成一个新列,将用户指定列的取值用下划线拼接。例如指定vehicle和color列时,执行以下代码可得到正确结果:
vehicles %>% mutate(category = paste(vehicle, color, sep = "_"))
结果:
| vehicle | color | speed | category |
|---|---|---|---|
| Car | Red | Low | Car_Red |
| Car | Black | High | Car_Black |
| Motorbike | Blue | High | Motorbike_Blue |
但要将此逻辑封装为函数,由用户传入字符向量(如choices = c("vehicle", "color", "speed"))指定拼接列。直接使用vehicles %>% mutate(category = paste(choices, sep = "_"))会生成全为"vehicle_color_speed"的列,无法得到手动输入列名时的正确结果,该怎么解决?
解决方案
这里提供三种可行的实现方式:
1. 使用dplyr::across + stringr::str_c(推荐)
这是tidyverse生态下的现代写法,代码简洁且可读性强:
library(dplyr) library(stringr) concat_columns <- function(data, target_cols, sep = "_") { data %>% mutate(category = str_c(across(all_of(target_cols)), collapse = sep, .names = NULL)) } # 调用示例:拼接vehicle、color、speed三列 concat_columns(vehicles, c("vehicle", "color", "speed"))
across(all_of(target_cols))会将字符向量转换为dplyr可识别的列对象,str_c的collapse参数会按行拼接每一行的指定列值。
2. 使用tidy求值(rlang::syms + !!!)
如果熟悉tidyverse的非标准求值语法,可以用这种方式实现:
library(dplyr) library(rlang) concat_columns <- function(data, target_cols, sep = "_") { data %>% mutate(category = paste(!!!syms(target_cols), sep = sep)) } # 调用示例:拼接vehicle和color列 concat_columns(vehicles, c("vehicle", "color"))
syms(target_cols)将字符向量转换为符号列表,!!!运算符会把这个列表展开为paste的多个参数,效果等同于手动输入列名。
3. 基础R实现(无tidyverse依赖)
如果不想依赖tidyverse包,用基础R的do.call也能实现:
concat_columns <- function(data, target_cols, sep = "_") { data$category <- do.call(paste, c(data[target_cols], sep = sep)) data } # 调用示例:拼接color和speed列 concat_columns(vehicles, c("color", "speed"))
data[target_cols]提取指定列组成子数据框,do.call(paste, ...)会将每一行的列值作为paste的参数完成拼接。
内容的提问来源于stack exchange,提问作者Alberto Agudo Dominguez
相关产品推荐
相关产品推荐

