【问题标题】:Discretization of zip codes to US regions in R在R中将邮政编码离散化到美国地区
【发布时间】:2014-11-12 01:22:12
【问题描述】:

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

我有字符数据

样本:

zip_code
'45654'
'12321'
'99453'

我有 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'

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

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

【问题讨论】:

    标签: r case geocoding discretization


    【解决方案1】:

    好的,很乱,但这可以工作。我假设您必须使用字符对象,因为某些邮政编码以 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" 
    

    【讨论】:

    • 请注意,这可能不是最优雅的解决方案,我相信其他人会加入其他解决方案
    • 可能有更优雅的解决方案,但您的解决方案很实用,这是我很难适应的思维框架。
    【解决方案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.table y 有列 cd 类似地表示一个范围。然后foverlaps(x,y)x 中的每一行查找y 中具有重叠范围的所有行。

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

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

    【讨论】:

      【解决方案3】:

      您也可以尝试(使用@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"
      

      【讨论】:

        猜你喜欢
        • 2011-01-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-09
        • 2019-08-19
        • 2011-01-05
        • 2021-11-26
        • 1970-01-01
        相关资源
        最近更新 更多