1

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

我有角色数据

样本:

zip_code
'45654'
'12321'
'99453'

ETC

我有 6 个有规则的类别:

1区-东北:01000-19999

区域 2 - SE:20000-39999

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

区域 4 - 西南:70000-79999,85000-88499

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

区域 6 - PC:90000-99999

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

region
'MW'
'NE'
'PC'

ETC

显然,我知道很多离散化数据的方法,但没有一个是干净和优雅的(比如循环、ifelse 等)

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

4

3 回答 3

2

这是一个 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 有列ab表示范围(例如,a<=b表示所有行),并且 data.tabley有列c并且d类似地表示范围。然后foverlaps(x,y)为 中的每一行查找具有重叠范围x的所有行。y

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

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

于 2014-11-12T06:14:14.803 回答
2

好的,很乱,但这可以工作。我假设您必须使用字符对象,因为某些邮政编码以 0 开头。 Obs。用您的邮政编码替换这些数字。

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" 
于 2014-11-12T01:41:32.290 回答
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"
于 2014-11-12T03:27:19.263 回答