邮政编码在美国地区的分离

时间:2014-11-12 01:22:13

标签: r case geocoding discretization

我想将带有邮政编码的数据离散化为区域

我有角色资料

样品:

zip_code
'45654'
'12321'
'99453'

我有6个规则类别:

区域1 - NE:01000-19999

区域2 - SE:20000-39999

3区 - MW:40000-58999,60000-69999

地区4 - SW:70000-79999,85000-88499

地区5 - MT:59000-59999,80000-84999,88900-89999

6区 - PC:90000-99999

我希望我的输出是因子数据:

region
'MW'
'NE'
'PC'

显然,我知道很多方法可以对数据进行离散化,但没有一种方法可以干净优雅(如循环,ifelse等)

是否有一种优雅的方法来应用具有6个类别的案例来离散这些数据?

3 个答案:

答案 0 :(得分:2)

好吧,凌乱但这可行。我假设您将不得不使用字符对象,因为一些邮政编码以0开头。用邮政编码替换这些数字。

zip_code <- c('1','6','15')
regions <- list(NE = as.character(1:3), 
        SE = as.character(4:6), 
        MW = as.character(7:9), 
        SW = as.character(10:12), 
        MT = as.character(13:15), 
        PC = as.character(16:19))
sapply(zip_code, function(x) names(regions[sapply(regions, function(y) x %in% y)]))

 1    6   15 
"NE" "SE" "MT" 

答案 1 :(得分:2)

以下是使用foverlaps(...)的data.table解决方案以及包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包含代表范围的列ab(例如a&lt; = {{1}对于所有行),data.table b具有列yc,类似地表示范围。然后dfoverlaps(x,y)中的每一行找到x中具有重叠范围的所有行。

在您的情况下,我们将y参数设置为区域,其中范围是每个(子)区域的开始和结束的zipcodes。然后我们使用实际的邮政编码(转换为整数)设置y作为原始邮政编码数据库,用于范围的开头和结尾。

x非常快。在这种情况下,完整的美国邮政编码数据库(> 44,000个邮政编码)在大约23毫秒内得到处理。

答案 2 :(得分:1)

您也可以尝试(使用@Scott Chamberlain的数据)

  with(stack(regions), unique(ind[ave(values %in% zip_code, ind, FUN=I)]))
 #[1] NE SE MT
 #Levels: MT MW NE PC SE SW

或者

 library(dplyr)
 library(tidyr)
 unnest(regions, region) %>%
                     group_by(region) %>%
                     filter(x %in% zip_code)

 # region x
 #1   NE  1
 #2   SE  6
 #3   MT 15

或者

 r1 <- vapply(regions, function(x) any(x %in% zip_code), logical(1))
 names(r1)[r1]
 #[1] "NE" "SE" "MT"