使用XML包和XPath从网站抓取地址时,有时我只能得到一个字符串,该字符串中嵌入了所需的邮政编码。提取邮政编码很简单,但是有时还会显示其他五位数的字符串。

这是关于df中问题的一些变体。

zips <- data.frame(id = seq(1, 5), address = c("Company, 18540 Main Ave., City, ST 12345", "Company 18540 Main Ave. City ST 12345-0000", "Company 18540 Main Ave. City State 12345", "Company, 18540 Main Ave., City, ST 12345 USA", "Company, One Main Ave Suite 18540, City, ST 12345"))

下面是用于提取邮政编码(5位数字和4位数字)的R语句,但是它受到街道编号和套房编号的人造邮政编码的欺骗(在其他地址字符串中可能还有其他可能性)。
regmatches(zips$address, gregexpr("\\d{5}([-]?\\d{4})?", zips$address, perl = TRUE))

对上一个SO问题的回答表明,“正则表达式将返回最后连续的五位数字符串。它使用负数预读以确保在返回五位数字符串之后不存在该五位数字符串。”
Extracting a zip code from an address string
\b\d{5}\b(?!.*\b\d{5}\b)

但是该问题与PHP有关,并提供了preg_matches()的if循环。

我的问题:哪种R代码将找到真实的邮政编码,而忽略错误的外观?

最佳答案

这是我的第一个regex答案(我仍在学习),因此希望我不会说错什么来引导您朝错误的方向发展。

基本上,正如您在问题中所提示的,此正则表达式查找的是看起来像邮政编码的最后一个字符串,而不是看起来像邮政编码的字符串

基本语法是pattern(?!.*pattern),它表示仅在不遵循pattern(?! )的情况下匹配.*(否定的前瞻性断言,语法:pattern)。

因此我们可以将模式替换为您感兴趣的内容:
[0-9]{5}(-[0-9]{4})?
也就是说,一个正好为5个字符的数字字符串[0-9] {5}(可以选择在另一个字符串后跟?,定义为连字符,另一个长度为四个(-[0-9]{4})
将所有内容与gregexpr一起搜索匹配项,并通过regmatches为我解释结果,我得到:

zips <- data.frame(id = seq(1, 5), address = c("Company, 18540 Main Ave., City, ST 12345", "Company 18540 Main Ave. City ST 12345-0000", "Company 18540 Main Ave. City State 12345", "Company, 18540 Main Ave., City, ST 12345 USA", "Company, One Main Ave Suite 18540, City, ST 12345"))
regmatches(zips$address,
           gregexpr('[0-9]{5}(-[0-9]{4})?(?!.*[0-9]{5}(-[0-9]{4})?)', zips$address, perl = TRUE))

# [[1]]
# [1] "12345"
#
# [[2]]
# [1] "12345-0000"
#
# [[3]]
# [1] "12345"
#
# [[4]]
# [1] "12345"
#
# [[5]]
# [1] "12345"

关于正则表达式提取美国邮政编码,但不提取虚假代码,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25180752/

10-12 22:33