如何为tidyr::extract定义正则参数以拆分指定短语列?
解决tidyr::extract拆分体重分类列的问题
你遇到的核心问题是需要让正则表达式匹配任意顺序的固定短语,并为每个短语单独生成一列,而不是按分隔符位置拆分。这里给你一个可以直接使用的正则表达式,完美适配你的需求:
library(tidyr) library(dplyr) sample %>% # 先把有序因子转为字符类型,避免正则匹配因子标签的索引问题 mutate(routine_provided_target = as.character(routine_provided_target)) %>% extract(routine_provided_target, c("routine_provided_uw", "routine_provided_hw", "routine_provided_ow", "routine_provided_vow"), # 核心正则表达式 regex = "^(?=.*?(Underweight))?(?=.*?(Healthy weight))?(?=.*?(Overweight))?(?=.*?(Very Overweight))?.*$", remove = FALSE)
正则表达式逻辑解释
这个正则的设计思路是用正向预查((?=...))来检测每个目标短语是否存在于字符串中,同时精准捕获对应的短语内容:
^和$:匹配字符串的开头和结尾,确保正则覆盖整个内容,避免遗漏或多余匹配(?=.*?(Underweight))?:正向预查字符串中是否存在Underweight,.*?表示尽可能少的匹配字符(避免跨短语误匹配),末尾的?允许该短语不存在(此时捕获组返回NA)- 同理,后面三个预查分别对应
Healthy weight、Overweight和Very Overweight - 最后的
.*匹配整个字符串,确保正则能完全匹配输入内容,避免因预查的零宽度特性导致匹配失败
这样,每个捕获组会对应一个固定短语:如果原字符串包含该短语,捕获组就会返回短语本身;如果不包含,则返回NA,完全符合你的需求。
效果验证
用你提供的样本数据测试:
- 对于值为
"Overweight,Very Overweight"的行,新列routine_provided_ow会是Overweight,routine_provided_vow会是Very Overweight,其余两列为NA - 对于值为
"Underweight,Healthy weight,Overweight,Very Overweight"的行,四个新列都会填充对应的完整短语 - 对于
NA值的行,四个新列也都是NA
同时,remove = FALSE会保留原列,新列会紧跟在原列之后,完全符合你对列顺序的要求。
内容的提问来源于stack exchange,提问作者gofraidh
相关产品推荐
相关产品推荐

