如何修正tidyr::separate_wider_regex正则以实现首个匹配拆分并忽略大小写?
解决tidyr::separate_wider_regex地址拆分的两个问题
1. 修正正则,实现首次匹配即拆分
你的问题根源是正则的贪婪匹配特性:默认情况下.*会尽可能匹配最长的内容,导致遇到「123 Cherry St Apt # 5」时,会匹配到最后一个符合规则的位置才拆分。要实现首次匹配就拆分,需改用非贪婪模式或正向预查来限定匹配范围。
错误示例(贪婪匹配)
如果你的原代码类似这样,就会出现匹配到最后的问题:
separate_wider_regex(df, address, patterns = list( building = "(.*)", unit = "(Apt.*)" ))
修正方案
给building的正则添加非贪婪限定符?,让它匹配到第一个公寓标识出现为止:
separate_wider_regex(df, address, patterns = list( building = "(.*?)", unit = "(Apt.*)" ))
更严谨的写法是用正向预查,确保building仅匹配到第一个空格+公寓标识之前的内容:
separate_wider_regex(df, address, patterns = list( building = "(.*?)(?=\\sApt)", unit = "(\\sApt.*)" ))
2. 实现不区分大小写匹配
有两种简单方法无需重复编写Apt/APT/apt等变体:
方式一:利用ignore_case参数
separate_wider_regex自带ignore_case参数,设为TRUE即可自动忽略大小写:
separate_wider_regex(df, address, patterns = list( building = "(.*?)(?=\\sApt)", unit = "(\\sApt.*)" ), ignore_case = TRUE)
方式二:正则内添加(?i)修饰符
如果需要更精准的局部控制,可在正则模式前加(?i)强制不区分大小写:
separate_wider_regex(df, address, patterns = list( building = "(.*?)(?=\\s(?i)Apt)", unit = "(\\s(?i)Apt.*)" ))
完整实操示例
假设你的数据如下:
library(tidyr) library(stringr) df <- tibble( address = c( "123 Cherry St Apt 5", "123 Cherry St Apt # 5", "456 Oak Ave APT 10B", "789 Pine Rd apt # 2C" ) )
运行修正后的拆分代码,再清理首尾空格:
df_cleaned <- separate_wider_regex(df, address, patterns = list( building = "(.*?)(?=\\sApt)", unit = "(\\sApt.*)" ), ignore_case = TRUE) %>% mutate(across(c(building, unit), str_trim))
最终拆分结果:
A tibble: 4 × 2building unit
1 123 Cherry St Apt 5
2 123 Cherry St Apt # 5
3 456 Oak Ave APT 10B
4 789 Pine Rd apt # 2C
内容的提问来源于stack exchange,提问作者bikeactuary
相关产品推荐
相关产品推荐

