这是一个 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.tabley
有列c
并且d
类似地表示范围。然后foverlaps(x,y)
为 中的每一行查找具有重叠范围x
的所有行。y
在您的情况下,我们将y
参数设置为区域,其中范围是每个(子)区域的开始和结束邮政编码。然后我们使用范围的开头和结尾的实际邮政编码(转换为整数)设置x
为原始邮政编码数据库。
foverlaps(...)
非常快。在这种情况下,完整的美国邮政编码数据库(>44,000 个邮政编码)在大约 23 毫秒内处理完毕。