这是一个 data.table 解决方案,使用 foverlaps(...) 和包 zipcode 中的完整美国邮政编码数据库作为示例。请注意,您对范围的定义是有缺陷的:例如,NH 中的邮政编码超出了NE 范围,而 PR 则完全缺失。
library(data.table) # 1.9.4+
library(zipcode)
data(zipcode) # database of US zip codes (a data frame)
zips <- data.table(zip_code=zipcode$zip)
regions <- data.table(region=c("NE" , "SE", "MW", "MW", "SW", "SW", "MT", "MT", "MT", "PC"),
start =c(01000,20000,40000,60000,70000,85000,59000,80000,88900,90000),
end =c(19999,39999,58999,69999,79999,88400,59999,84999,89999,99999))
setkey(regions,start,end)
zips[,c("start","end"):=list(as.integer(zip_code),as.integer(zip_code))]
result <- foverlaps(zips,regions)[,list(zip_code,region)]
result[sample(1:nrow(result),10)] # random sample of the result
# zip_code region
# 1: 27113 SE
# 2: 36101 SE
# 3: 55554 MW
# 4: 91801 PC
# 5: 20599 SE
# 6: 90250 PC
# 7: 95329 PC
# 8: 63435 MW
# 9: 60803 MW
# 10: 07040 NE
foverlaps(...) 以这种方式工作:假设 data.table x 具有表示范围的列 a 和 b(例如,a b 表示所有行)和 data.table y 有列 c 和 d 类似地表示一个范围。然后foverlaps(x,y) 为x 中的每一行查找y 中具有重叠范围的所有行。
在您的情况下,我们将 y 参数设置为区域,其中范围是每个(子)区域的开始和结束邮政编码。然后我们将x 设置为原始邮政编码数据库,使用实际邮政编码(转换为整数)作为范围的开头和结尾。
foverlaps(...) 非常快。在这种情况下,整个美国邮政编码数据库(>44,000 个邮政编码)的处理时间约为 23 毫秒。