如何正确使用separate_wider_regex()处理正则匹配失败场景?
解决separate_wider_regex()处理格式不一致地址字符串的问题
问题说明
使用separate_wider_regex()拆分地址字符串时,当部分字符串缺少str-la标识,会导致后续的街道名称(den_str)和门牌号(nr)无法正确提取。现有代码在格式统一的moldavia_1中正常工作,但在存在格式差异的moldavia_2中返回大量NA,无法得到预期结果。
待处理的数据:
moldavia_2 <- tibble(adresa = c("1;MD-3101,Balti Botu Pavel 3", "3;MD-3102,Balti str-la Muresanu A. 11", "17;MD-3102,Balti Sorocii 46", "398;MD-3111,Balti Stefan cel Mare 20", "1130;MD-3128,Balti str-la Lvovului 2", "1252;MD-3128,Balti str-la Lvovului 1", "2814;MD-3102,Balti Cahulului 44"))
期望的拆分结果是即使没有str-la,也能正确提取所有字段,包括将缺少str-la的行对应字段设为NA,同时完整提取街道名称和门牌号。
调整后的解决方案
关键是将str-la设置为可选匹配,并调整正则逻辑适配两种格式,具体代码如下:
library(tidyverse) moldavia_2 %>% separate_wider_regex( cols = adresa, patterns = c( ids = "^\\d+", ";", cod_post = ".*?", # 非贪婪匹配,确保只捕获到逗号前的邮编 ",", cod_4 = "\\w+", "\\s", str = "(str-la)?", # 将str-la设为可选匹配,无匹配时返回NA "(?(1)\\s|)", # 条件匹配:若存在str-la则匹配后续空格,否则跳过 den_str = "(.*?)(?=\\s\\d+$)", # 匹配到最后空格+数字前的所有内容,即街道名称 "\\s", nr = "\\d+$" ), too_few = "align_start" ) %>% rename(tip_str = str) # 重命名为期望的列名
关键调整点
cod_post的非贪婪匹配:将原来的.*改为.*?,避免过度匹配吃掉逗号后的内容,确保准确捕获邮编。- 可选的
str-la匹配:用(str-la)?让该字段成为可选,无匹配时自动返回NA。 - 条件正则适配格式差异:
(?(1)\\s|)是条件分支正则,当str-la匹配成功时,才匹配后续的空格,解决有无str-la时的格式差异。 - 精准捕获街道名称:
(.*?)(?=\\s\\d+$)通过正向预查,匹配到最后一个空格加门牌号之前的所有内容,不管有没有str-la都能正确提取街道名称,同时去掉多余的引号和空格。
运行结果
执行后将得到与期望一致的输出:
# A tibble: 7 × 6 ids cod_post cod_4 tip_str den_str nr <chr> <chr> <chr> <chr> <chr> <chr> 1 1 MD-3101 Balti NA Botu Pavel 3 2 3 MD-3102 Balti str-la Muresanu A. 11 3 17 MD-3102 Balti NA Sorocii 46 4 398 MD-3111 Balti NA Stefan cel Mare 20 5 1130 MD-3128 Balti str-la Lvovului 2 6 1252 MD-3128 Balti str-la Lvovului 1 7 2814 MD-3102 Balti NA Cahulului 44
内容的提问来源于stack exchange,提问作者itamar
相关产品推荐
相关产品推荐

