如何在R语言中利用正则表达式处理数据集并提取指定模式列?
R语言数据处理:提取特定模式列并重组数据集
原始数据集
id = 1:5 col1 = c("john", "henry", "adam", "jenna", "peter") col2 = c("river B8C 9L4", "Field U9H 5E2 PP", "NA", "ocean A1B 5H1 dd", "dave") col3 = c("matt", "steve", "forest K0Y 1U9 hu2", "NA", "NA") col4 = c("Phone: 111 1111 111", "Phone: 222 2222", "Phone: 333 333 1113", "Phone: 444 111 1153", "Phone: 111 111 1121") my_data = data.frame(id, col1, col2, col3, col4)
数据结构:
id col1 col2 col3 col4 1 1 john river B8C 9L4 matt Phone: 111 1111 111 2 2 henry Field U9H 5E2 PP steve Phone: 222 2222 3 3 adam NA forest K0Y 1U9 hu2 Phone: 333 333 1113 4 4 jenna ocean A1B 5H1 dd NA Phone: 444 111 1153 5 5 peter dave NA Phone: 111 111 1121
需求
- 始终保留
id列和col1列 - 提取包含
LETTER NUMBER LETTER NUMBER LETTER NUMBER模式的列内容生成new_col - 始终保留电话号码所在的
col4列
期望结果
id col1 new_col col4 1 1 john river B8C 9L4 Phone: 111 1111 111 2 2 henry Field U9H 5E2 PP Phone: 222 2222 3 3 adam forest K0Y 1U9 hu2 Phone: 333 333 1113 4 4 jenna ocean A1B 5H1 Phone: 444 111 1153
现有正则代码
apply(my_data, 1, function(x) gsub('(([A-Z] ?[0-9]){3})|.', '\\1', toString(x))) # 输出:[1] "B8C 9L4" "U9H 5E2" "K0Y 1U9" "A1B 5H1" ""
解决方案
你的正则已经能定位目标模式,但需要匹配包含该模式的整段文本而非仅提取模式本身。以下是两种实现方式:
方法一:使用dplyr逐行处理
library(dplyr) # 定义提取函数:保留包含目标模式的文本,清理多余后缀 extract_target <- function(str) { pattern <- "([A-Z][0-9][A-Z] [0-9][A-Z][0-9])" if (grepl(pattern, str)) { # 保留模式及前面的文本,去掉模式后多余的非有效字符 return(sub("(.*[A-Z][0-9][A-Z] [0-9][A-Z][0-9])\\W.*", "\\1", str)) } else { return(NA) } } # 处理数据集 my_result <- my_data %>% rowwise() %>% mutate(new_col = case_when( grepl("([A-Z][0-9][A-Z] [0-9][A-Z][0-9])", col2) ~ extract_target(col2), grepl("([A-Z][0-9][A-Z] [0-9][A-Z][0-9])", col3) ~ extract_target(col3), TRUE ~ NA_character_ )) %>% select(id, col1, new_col, col4) %>% filter(!is.na(new_col)) print(my_result)
方法二:基础R实现(无依赖)
# 定义提取函数 extract_target <- function(str) { pattern <- "([A-Z][0-9][A-Z] [0-9][A-Z][0-9])" if (grepl(pattern, str)) { return(sub("(.*[A-Z][0-9][A-Z] [0-9][A-Z][0-9])\\W.*", "\\1", str)) } else { return(NA) } } # 逐行生成new_col new_col <- character(nrow(my_data)) for (i in 1:nrow(my_data)) { if (grepl("([A-Z][0-9][A-Z] [0-9][A-Z][0-9])", my_data$col2[i])) { new_col[i] <- extract_target(my_data$col2[i]) } else if (grepl("([A-Z][0-9][A-Z] [0-9][A-Z][0-9])", my_data$col3[i])) { new_col[i] <- extract_target(my_data$col3[i]) } else { new_col[i] <- NA } } # 组合结果并过滤无效行 my_result <- data.frame( id = my_data$id, col1 = my_data$col1, new_col = new_col, col4 = my_data$col4 ) %>% filter(!is.na(new_col)) print(my_result)
代码说明
- 正则
([A-Z][0-9][A-Z] [0-9][A-Z][0-9])精准匹配你需要的字母数字交替模式 extract_target函数保留模式及前面的前缀文本,同时清理模式后的多余后缀(比如第4行的dd)- 通过逐行判断
col2和col3哪个包含目标模式,将对应内容赋值给new_col - 最后保留指定列并过滤无匹配的行(比如第5行的
peter)
内容的提问来源于stack exchange,提问作者stats_noob
相关产品推荐
相关产品推荐

