R中的地理编码地址:grep()查找world.cities数据集

时间:2014-09-12 13:36:58

标签: regex r geocode

我正在尝试对存储在字符向量中的一些地址进行地理编码。我在geocode()中使用了ggmaps函数;但是,它只对我的地址的50%进行了分类。我希望使用更基本的方法来查找城市名称(来自world.cities包中的maps数据是否在我的地址列表中,如果是,请从中获取经度和纬度信息这个查找表。我会尝试清理返回的文件,并用R提供的其他地理编码方法(调用各种外部API)来补充它。到目前为止我编写的内容如下:

places <- c("Atlanta,Georgia", "My house, Paris, France", "Some Other House, Paris, Ontario, Canada", "Paris", "Oxford", "Oxford, USA")

library(maps)
data(world.cities)
ddd <- world.cities[world.cities$name %in% c("Paris","Oxford","New York"),]

is.integer0 <- function(x) {
is.integer(x) && length(x) == 0L
}

for (i in 1:length(places)) {
  for (j in 1:dim(ddd)[1]) {
  k <- ddd$name[j]
    if (is.integer0(grep(k,places[i],perl=TRUE))==TRUE) next
      if (exists("zzz")==FALSE) {
        zzz <- cbind(places[i],ddd[j,1:5])
      } else {
        zzz <- rbind(zzz,cbind(places[i],ddd[j,1:5])) 
      } 
  }
}

输出是我想要的(我稍后会主观地清理它)。我的问题是我的真实数据大约是8000个地址,而world.cities数据大约是40000多个城市,所以双循环方法有点慢。与R中的其他任务一样,我认为可以使用apply系列的某个成员进行矢量化。我无法理解如何做到这一点。有什么想法吗?

### Output
                                      places[i]   name country.etc     pop    lat  long
28245                   My house, Paris, France  Paris      Canada   10570  43.20  0.38
28246                   My house, Paris, France  Paris      France 2141839  48.86   2.34
282451 Some Other House, Paris, Ontario, Canada  Paris      Canada   10570  43.20 -80.38
282461 Some Other House, Paris, Ontario, Canada  Paris      France 2141839  48.86   2.34
282452                                    Paris  Paris      Canada   10570  43.20 -80.38
282462                                    Paris  Paris      France 2141839  48.86   2.34
27671                                    Oxford Oxford      Canada    1271  45.73 -63.87
27672                                    Oxford Oxford New Zealand    1816 -43.30 172.18
27673                                    Oxford Oxford          UK  157568  51.76  -1.26
276711                              Oxford, USA Oxford      Canada    1271  45.73 -63.87
276721                              Oxford, USA Oxford New Zealand    1816 -43.30 172.18
276731                              Oxford, USA Oxford          UK  157568  51.76  -1.26

经过一些进一步的数据清理后,我真的想要:

### Output
                                      places[i]   name country.etc     pop    lat  long
 28246                   My house, Paris, France  Paris      France 2141839  48.86   2.34
282451 Some Other House, Paris, Ontario, Canada  Paris      Canada   10570  43.20 -80.38
282462                                    Paris  Paris      France 2141839  48.86   2.34
27673                                    Oxford Oxford          UK  157568  51.76  -1.26
276731                              Oxford, USA Oxford          NA       NA    NA  NA
                               Atlanta, Georgia     NA          NA       NA    NA  NA

基本上,逻辑是:

  1. 如果国家/地区也匹配地点字符串,请保留该行。巴黎,法国和加拿大巴黎的例子。
  2. 如果places字符串包含单个单词,则猜测它们指的是人口最多的城市。所以默认巴黎到巴黎,法国和牛津到牛津英国。由于很难对非唯一地址进行地理编码。
  3. 如果places字符串包含多个单词但Country不匹配任何其他单词,例如Oxford,USA。然后做除了城市NA以外的一切。在这里,我将试试geocode()和其他服务,以获得更好的信息。
  4. 如果地址地址永远不在查找字典中,请添加它,然后尝试使用geocode()等填写所有内容(实际上我只想要长/纬度)。这就是亚特兰大乔治亚州的例子。
  5. 关于一般方法的思考以及如何在R中做得更好?如上所述,这种方法的动力是看我是否可以补充我已经获得的东西(使用geocode()函数的50%地理编码地址)

1 个答案:

答案 0 :(得分:2)

这使得城市提取更通用(使用字符串正则表达式匹配),然后与world.cities数据合并:

places_dat <- cbind(places, Reduce(rbind, 
                lapply(str_match_all(places, ",*\ *([[:alpha:]]+)\ *,\ *([[:alpha:]]+)\ *$"),
                  function(x) {

  if (length(x) == 0) {
    return(data.frame(city=NA, state=NA))
  } else {
    return(data.frame(city=x[,2], state=x[,3]))
  }

})))

places_dat

##                                     places    city   state
## 1                          Atlanta,Georgia Atlanta Georgia
## 2                  My house, Paris, France   Paris  France
## 3 Some Other House, Paris, Ontario, Canada Ontario  Canada
## 4                                    Paris    <NA>    <NA>
## 5                                   Oxford    <NA>    <NA>
## 6                              Oxford, USA  Oxford     USA
## 

merge(places_dat, world.cities, by.x="city", by.y="name", all.x=TRUE)

##      city                                   places   state country.etc     pop    lat    long capital
## 1 Atlanta                          Atlanta,Georgia Georgia         USA  424096  33.76  -84.42       0
## 2   Paris                  My house, Paris, France  France      France 2141839  48.86    2.34       1
## 3   Paris                  My house, Paris, France  France      Canada   10570  43.20  -80.38       0
## 4 Ontario Some Other House, Paris, Ontario, Canada  Canada         USA  175805  34.05 -117.61       0
## 5  Oxford                              Oxford, USA     USA      Canada    1271  45.73  -63.87       0
## 6  Oxford                              Oxford, USA     USA New Zealand    1816 -43.30  172.18       0
## 7  Oxford                              Oxford, USA     USA          UK  157568  51.76   -1.26       0
## 8    <NA>                                    Paris    <NA>        <NA>      NA     NA      NA      NA
## 9    <NA>                                   Oxford    <NA>        <NA>      NA     NA      NA      NA

它仍然需要一些筛选(可能complete.cases作为一步),但它会让你更进一步,并且应该更快一点。