【问题标题】:R: Mission impossible? How to assign "New York" to a countyR:不可能的任务?如何将“纽约”分配给县
【发布时间】:2017-11-28 23:21:41
【问题描述】:

我在将县分配给某些城市时遇到了问题。通过acs包查询时

> geo.lookup(state = "NY", place = "New York")
  state state.name                                                                 county.name place             place.name
1    36   New York                                                                        <NA>    NA                   <NA>
2    36   New York Bronx County, Kings County, New York County, Queens County, Richmond County 51000          New York city
3    36   New York                                                               Oneida County 51011 New York Mills village

,例如,您可以看到“纽约”有一堆县。洛杉矶、波特兰、俄克拉荷马州、哥伦布等地也是如此。如何将这些数据分配给“县”?

以下代码当前用于将“county.name”与相应的县 FIPS 代码匹配。不幸的是,它仅适用于查询中仅输出一个县名的情况。

脚本

dat <- c("New York, NY","Boston, MA","Los Angeles, CA","Dallas, TX","Palo Alto, CA")
dat <- strsplit(dat, ",")
dat

library(tigris)
library(acs)
data(fips_codes) # FIPS codes with state, code, county information

GeoLookup <- lapply(dat,function(x) {
  geo.lookup(state = trimws(x[2]), place = trimws(x[1]))[2,]
})

df <- bind_rows(GeoLookup)

#Rename cols to match
colnames(fips_codes) = c("state.abb", "statefips", "state.name", "countyfips", "county.name")

# Here is a problem, because it works with one item in "county.name" but not more than one (see output below).

df <- df %>% left_join(fips_codes, by = c("state.name", "county.name"))
df

返回:

  state    state.name                                                                  county.name place           place.name state.abb statefips countyfips
1    36      New York  Bronx County, Kings County, New York County, Queens County, Richmond County 51000        New York city      <NA>      <NA>       <NA>
2    25 Massachusetts                                                               Suffolk County  7000          Boston city        MA        25        025
3     6    California                                                           Los Angeles County 20802 East Los Angeles CDP        CA        06        037
4    48         Texas Collin County, Dallas County, Denton County, Kaufman County, Rockwall County 19000          Dallas city      <NA>      <NA>       <NA>
5     6    California                                                             San Mateo County 20956  East Palo Alto city        CA        06        081

为了保留数据,left_join 最好匹配为“查找包含 place.namecounty.name(名称中不附加 xy city ),或者默认选择第一项。很高兴看到如何做到这一点。

总的来说:我认为,没有比这种方法更好的方法了吗?

感谢您的帮助!

【问题讨论】:

    标签: r dplyr match geocoding acs


    【解决方案1】:

    下面的代码如何创建用于连接的“长”数据框。我们使用tidyverse 管道运算符来链接操作。 strsplit 返回一个列表,我们 unnest 将列表值(与 state.nameplace.name 的每个组合一起使用的县名)堆叠到一个长数据框中,其中每个 county.name 现在都有自己的行.

    library(tigris)
    library(acs)  
    library(tidyverse)
    
    dat = geo.lookup(state = "NY", place = "New York")  
    
      state state.name                                                                 county.name place             place.name
    1    36   New York                                                                        <NA>    NA                   <NA>
    2    36   New York Bronx County, Kings County, New York County, Queens County, Richmond County 51000          New York city
    3    36   New York                                                               Oneida County 51011 New York Mills village
    
    dat = dat %>% 
      group_by(state.name, place.name) %>% 
      mutate(county.name = strsplit(county.name, ", ")) %>% 
      unnest
    
      state state.name place             place.name     county.name
      <chr>      <chr> <int>                  <chr>           <chr>
    1    36   New York    NA                   <NA>            <NA>
    2    36   New York 51000          New York city    Bronx County
    3    36   New York 51000          New York city    Kings County
    4    36   New York 51000          New York city New York County
    5    36   New York 51000          New York city   Queens County
    6    36   New York 51000          New York city Richmond County
    7    36   New York 51011 New York Mills village   Oneida County
    

    更新:关于您评论中的第二个问题,假设您已经拥有都市区的向量,这个怎么样:

    dat <- c("New York, NY","Boston, MA","Los Angeles, CA","Dallas, TX","Palo Alto, CA")
    
    df <- map_df(strsplit(dat, ", "), function(x) {
      geo.lookup(state = x[2], place = x[1])[-1, ] %>% 
        group_by(state.name, place.name) %>%
        mutate(county.name = strsplit(county.name, ", ")) %>%
        unnest
    })
    
    df
    
       state    state.name place             place.name        county.name
     1    36      New York 51000          New York city       Bronx County
     2    36      New York 51000          New York city       Kings County
     3    36      New York 51000          New York city    New York County
     4    36      New York 51000          New York city      Queens County
     5    36      New York 51000          New York city    Richmond County
     6    36      New York 51011 New York Mills village      Oneida County
     7    25 Massachusetts  7000            Boston city     Suffolk County
     8    25 Massachusetts  7000            Boston city     Suffolk County
     9     6    California 20802   East Los Angeles CDP Los Angeles County
    10     6    California 39612   Lake Los Angeles CDP Los Angeles County
    11     6    California 44000       Los Angeles city Los Angeles County
    12    48         Texas 19000            Dallas city      Collin County
    13    48         Texas 19000            Dallas city      Dallas County
    14    48         Texas 19000            Dallas city      Denton County
    15    48         Texas 19000            Dallas city     Kaufman County
    16    48         Texas 19000            Dallas city    Rockwall County
    17    48         Texas 40516       Lake Dallas city      Denton County
    18     6    California 20956    East Palo Alto city   San Mateo County
    19     6    California 55282         Palo Alto city Santa Clara County
    

    更新 2: 如果我了解您的 cmets,对于具有多个县的城市(实际上是示例中的地名),我们只需要与城市名称相同的县(例如例如,如果是纽约市,则为纽约县),否则为列表中的第一个县。以下代码选择与城市同名的县,如果没有,则选择该城市的第一个县。您可能需要对其进行一些调整以使其适用于整个美国。例如,要使其适用于路易斯安那州,您可能需要 gsub(" County| Parish"... 而不是 gsub(" County"...

    map_df(strsplit(dat, ", "), function(x) {
      geo.lookup(state = x[2], place = x[1])[-1, ] %>% 
        group_by(state.name, place.name) %>%
        mutate(county.name = strsplit(county.name, ", ")) %>%
        unnest %>% 
        slice(max(1, which(grepl(sub(" [A-Za-z]*$","", place.name), gsub(" County", "", county.name))), na.rm=TRUE))
    })
    
       state    state.name place             place.name        county.name
       <chr>         <chr> <int>                  <chr>              <chr>
     1    36      New York 51000          New York city    New York County
     2    36      New York 51011 New York Mills village      Oneida County
     3    25 Massachusetts  7000            Boston city     Suffolk County
     4     6    California 20802   East Los Angeles CDP Los Angeles County
     5     6    California 39612   Lake Los Angeles CDP Los Angeles County
     6     6    California 44000       Los Angeles city Los Angeles County
     7    48         Texas 19000            Dallas city      Dallas County
     8    48         Texas 40516       Lake Dallas city      Denton County
     9     6    California 20956    East Palo Alto city   San Mateo County
    10     6    California 55282         Palo Alto city Santa Clara County
    

    【讨论】:

    • 这是个好方法!在这个例子中,我如何首先选择(可能)包含字符串“New York”的县,而不是默认使用“Queens”?另外:您如何将其包含在上面的 GeoLookup 函数中?如您所见,我目前默认使用“[2,]”作为第二行。也许有更好的方法?谢谢!
    • 你能多谈谈你的第一个问题吗?您的意思是当place.nameNew York city 时,您希望county.name 中的所有值都为New York County?您希望应用的一般规则是什么?
    • 实际上,问题是“纽约”尚未分配到任何县。所以我喜欢将它(1)分配给与城市名称“New York”的字符串匹配的县,或者(2)默认情况下列表中的第二个输出(第一个带有县名)。关于 (2) 我知道这并不完美,但可能是将城市分配给任何县的唯一方法。
    • 它可能需要是 "dat %>% "filter(str_detect(county.name, "city name"))" 但带有 (1) 或 (2) 选项。跨度>
    • 逻辑可能类似于:a) 如果 nrow(outputof geo.lookup) = 2,取第二行,否则 b) 如果 geo.lookup county.name 包含逗号(表示超过一个县),然后 b.1) [strsplit, unnest part of your code] 并选择place = 输入字符串与county.name 字段匹配的行,或b.2) 选择第二行。
    【解决方案2】:

    你能用下面的代码来准备数据吗?

    new_york_data <- geo.lookup(state = "NY", place = "New York")
    
    prep_data <- function(full_data){
      output <- data.frame()
      for(row in 1:nrow(full_data)){
        new_rows <- replicateCounty(full_data[row, ])
        output <- plyr::rbind.fill(output, new_rows)
      }
      return(output)
    }
    
    
    replicateCounty <- function(row){
      counties <- str_trim(unlist(str_split(row$county.name, ",")))
    
      output <- data.frame(state = row$state,
                           state.name = row$state.name,
                           county.name = counties,
                           place = row$place,
                           place.name = row$place.name)
    
      return(output)
    }
    
    prep_data(new_york_data)
    

    有点乱,你需要 plyr 和 stringr 包。准备好数据后,您应该可以加入其中

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-09-17
      • 1970-01-01
      • 1970-01-01
      • 2014-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多