R语言campfin包normal_address()函数未按预期工作的问题排查
关于R语言campfin包normal_address()函数的地址标准化问题
问题场景
使用campfin包的normal_address()函数时,无法完全将街道全称替换为USPS标准缩写,导致后续模糊匹配失效。执行代码如下:
df <- df %>% mutate(clean_add = normal_address(RESERVATION_ADDRESS, abbs=usps_street))
未正确标准化的样本数据:
structure(list(RESERVATION_ADDRESS = c("4620 ASH GROVE DRIVE #3B", "4001 DE MORADA DRIVE UNIT 118", "734 THOMPSON DRIVE, UNIT A", "5917 YORK BRIDGE CIRCLE, AUSTIN, TX", "4140 SUNLAND CIRCLE NW", "3951 BELLAIRE DRIVE SOUTH"), RESERVATION_CITY = c("SPRINGFIELD", "ODESSA", "LAKE DALLAS", "AUSTIN", "ALBUQUERQUE", "FORT WORTH" ), RESERVATION_STATE = c("IL", "TX", "TX", "TX", "NM", "TX"), RESERVATION_ZIPCODE = c(62711, 79765, 75065, 78749, 87107, 76109)), row.names = c(NA, 6L), class = "data.frame")
不想用gsub逐个替换(如gsub("CIRCLE", "CIR", clean_add)),担心遗漏同类情况,需确认是操作错误还是函数问题,并寻求更优的地址标准化方案。
问题分析
1. 是操作错误还是函数局限?
这并非操作错误,而是normal_address()的匹配逻辑存在局限:
- 函数默认匹配独立完整的单词,如果街道后缀和方向词(如NW、SOUTH)连在一起,或地址中混入城市/州信息(比如样本里的"AUSTIN, TX"),会干扰后缀识别
- 地址里的后缀如果带逗号等标点,也会破坏函数的精确匹配规则
比如样本中"CIRCLE NW",函数无法将"CIRCLE"单独识别为后缀进行替换;带城市的地址行,后缀被冗余信息干扰,同样无法触发替换。
替代解决方案
方案一:优化campfin现有逻辑
先清理地址中的冗余信息,拆分粘连的方向词和后缀,再调用normal_address():
library(campfin) library(dplyr) library(stringr) df_clean <- df %>% mutate( # 移除地址中混入的城市、州信息 RESERVATION_ADDRESS = str_remove(RESERVATION_ADDRESS, ",\\s*[A-Za-z\\s]+,\\s*[A-Z]{2}"), # 拆分后缀与方向词(比如把"CIRCLE NW"拆为独立单词) RESERVATION_ADDRESS = str_replace(RESERVATION_ADDRESS, "([A-Z]+)(\\s*[A-Z]{2})$", "\\1 \\2") ) %>% mutate(clean_add = normal_address(RESERVATION_ADDRESS, abbs = usps_street))
方案二:使用postmastr包(专业地址标准化)
postmastr是专门处理美国地址的工具,完全遵循USPS规则,能自动识别后缀、方向词、单元信息:
library(postmastr) # 重命名列以适配postmastr要求 df_pm <- df %>% rename( address = RESERVATION_ADDRESS, city = RESERVATION_CITY, state = RESERVATION_STATE, zip = RESERVATION_ZIPCODE ) # 执行标准化,输出USPS缩写格式 df_pm_clean <- df_pm %>% pm_identify(type = "us") %>% pm_parse() %>% pm_compose(output = "short")
方案三:结合地理编码实现精准标准化
通过免费的美国人口普查局API进行地理编码,直接返回官方标准化地址:
library(tidygeocoder) df_geo <- df %>% geocode( address = str_c(RESERVATION_ADDRESS, RESERVATION_CITY, RESERVATION_STATE, RESERVATION_ZIPCODE, sep = ", "), method = "census", full_results = TRUE ) %>% select(standardized_address = address) # 提取标准化后的地址
内容的提问来源于stack exchange,提问作者doing_data
相关产品推荐
相关产品推荐

