如何向dplyr的mutate传递命名列表/字符值批量生成数据框列?
批量生成数据框新列的解决方案
一、修复命名列表方法
你之前的condition1存储的是字符串,但mutate需要的是表达式对象而非字符串。用rlang::parse_expr()将每个字符串解析为表达式,再通过!!!注入到mutate中即可生效:
library(dplyr) library(rlang) # 解析字符串为表达式 condition1 <- list( parse_expr("case_when(grepl('^Mazda', model) ~ 1, TRUE ~ 0)"), parse_expr("case_when(grepl('^Merc', model) ~ 1, TRUE ~ 0)"), parse_expr("case_when(grepl('^Volvo', model) ~ 1, TRUE ~ 0)") ) names(condition1) <- c("MAZDA", "MERC", "VOLVO") # 执行批量列生成 result1 <- mtcars %>% rownames_to_column("model") %>% mutate(!!!condition1)
如果是动态生成品牌规则,还可以用map批量构建表达式,避免重复代码:
library(glue) brands <- c("MAZDA" = "^Mazda", "MERC" = "^Merc", "VOLVO" = "^Volvo") condition1 <- map(brands, ~parse_expr(glue("case_when(grepl('{.x}', model) ~ 1, TRUE ~ 0)"))) result1 <- mtcars %>% rownames_to_column("model") %>% mutate(!!!condition1)
二、修复字符字符串方法
直接在mutate中使用eval(parse(text=condition2))会报错,因为parse(text=condition2)返回的是多表达式集合,需要用parse_exprs()解析为表达式列表,再通过!!!注入:
library(dplyr) library(rlang) condition2 <- "MAZDA = case_when(grepl('^Mazda', model) ~ 1, TRUE ~ 0), MERC = case_when(grepl('^Merc', model) ~ 1, TRUE ~ 0), VOLVO = case_when(grepl('^Volvo', model) ~ 1, TRUE ~ 0)" result2 <- mtcars %>% rownames_to_column("model") %>% mutate(!!!parse_exprs(condition2))
三、base R替代方案
无需依赖dplyr,用grepl结合cbind即可实现批量列生成:
# 将行名转为单独列 mtcars_with_model <- cbind(model = rownames(mtcars), mtcars) # 定义品牌匹配规则 brands <- list(MAZDA = "^Mazda", MERC = "^Merc", VOLVO = "^Volvo") # 批量生成新列(将逻辑值转为0/1整数) new_cols <- sapply(brands, function(pattern) as.integer(grepl(pattern, mtcars_with_model$model))) # 合并新列到原数据框 result_base <- cbind(mtcars_with_model, new_cols)
内容的提问来源于stack exchange,提问作者MatSchu
相关产品推荐
相关产品推荐

