基于dplyr实现动态命名多列,判断招聘要求是否含指定编程语言
问题
现有包含职位空缺要求的字符串数据框df,以及存储编程语言名称的字符串向量prog_langs,需要用优雅的dplyr实现方式,在mutate中为每种编程语言生成新列,列名格式为ProgLang_{编程语言名},新列值为布尔值,标记对应行的职位要求是否包含该编程语言。
用户提供的示例代码如下(存在用法错误):
# 自定义函数 is_contains = function(txt, cond) if(grepl(cond, txt)) return(TRUE) else return(FALSE) # 编程语言向量 prog_langs = c("python", "java", "sql", "html") # 包含职位空缺要求的字符串数据框 df = data.frame("string" = c("exposure to scripting or programming languages (e.g python, c+, or powershell).", "scripting skills (e.g. java, javascript, beanshell, etc.)", "basic understanding of sql", "html and css knowledge is a must.")) # 示例代码(存在错误) df %>% mutate(across(.cols = vars(prog_langs), .fns = function(x) is_contains(txt = string, cond = x), .names = 'ProgLang_{.col}'))
期望输出:生成包含N个新列的df(N为prog_langs长度),每个新列值为TRUE或FALSE。
解决方案
示例代码的核心问题是across(.cols = vars(prog_langs))用法错误:across的.cols参数用于指定数据框已存在的列,而非外部向量。以下是两种优雅的dplyr实现方案:
方案一:结合purrr::map_dfc批量生成列
利用map_dfc批量生成包含检测结果的列,再通过mutate整合到原数据框:
library(dplyr) library(purrr) # 定义编程语言向量与原始数据框 prog_langs = c("python", "java", "sql", "html") df = data.frame( string = c( "exposure to scripting or programming languages (e.g python, c+, or powershell).", "scripting skills (e.g. java, javascript, beanshell, etc.)", "basic understanding of sql", "html and css knowledge is a must." ) ) # 生成目标数据框 df_new = df %>% mutate( map_dfc(prog_langs, ~ tibble(!!paste0("ProgLang_", .x) := grepl(.x, string, ignore.case = TRUE))) )
方案二:用across配合命名函数列表
先将编程语言向量转换为命名函数列表,再通过across迭代生成新列:
library(dplyr) library(purrr) # 定义编程语言向量与原始数据框 prog_langs = c("python", "java", "sql", "html") df = data.frame( string = c( "exposure to scripting or programming languages (e.g python, c+, or powershell).", "scripting skills (e.g. java, javascript, beanshell, etc.)", "basic understanding of sql", "html and css knowledge is a must." ) ) # 生成命名函数列表:键为目标列名,值为对应检测函数 lang_funs = setNames( map(prog_langs, ~ function(x) grepl(.x, x, ignore.case = TRUE)), paste0("ProgLang_", prog_langs) ) # 生成目标数据框 df_new = df %>% mutate(across(.cols = string, .fns = lang_funs, .names = "{.fn}"))
额外优化说明
- 无需自定义
is_contains函数,直接使用grepl即可实现包含检测;添加ignore.case = TRUE可忽略大小写差异,适配职位要求中编程语言的不同写法(如Python、PYTHON)。 - 两种方案均会生成符合要求的新列,列名格式为
ProgLang_python、ProgLang_java等,值为TRUE(包含对应语言)或FALSE(不包含)。
内容的提问来源于stack exchange,提问作者Jeparov
相关产品推荐
相关产品推荐

