使用googleway对

时间:2018-07-24 18:24:25

标签: r list geocoding nested-lists googleway

我已阅读Batch Geocoding with googleway R

我正在尝试使用googleway对某些地址进行地理编码。我要返回地理编码,地址和县。

使用上面链接的答案,我创建了以下功能。

geocodes<-lapply(seq_along(res),function(x) {
  coordinates<-res[[x]]$results$geometry$location
  df<-as.data.frame(unlist(res[[x]]$results$address_components))
  address<-paste(df[1,],df[2,],sep = " ")
  city<-paste0(df[3,])
  county<-paste0(df[4,])
  state<-paste0(df[5,])
  zip<-paste0(df[7,])
  coordinates<-cbind(coordinates,address,city,county,state,zip)
  coordinates<-as.data.frame(coordinates)
})

然后像这样把它放回去...

library(data.table)

done<-rbindlist(geocodes))

问题是要从“ res”列表中删除地址和县。上面链接的答案从发送到google的数据框中提取地址,并假定列表顺序正确,并且google没有返回多个匹配结果(在我的列表中似乎有几个)。重点是,从一个文件中获取地址而从另一个文件中获取坐标似乎很鲁ck,并且由于无论如何我都需要县,所以我需要一种方法将其从保存在“ res”中的Google结果列表中拉出。

问题在于某些地址比其他地址具有更多的“类型”,这意味着像我上面所做的那样按行引用是行不通的。

我还尝试将rbindlist包含在函数中,以将子列表转换为数据表,然后拉出字段,但不能完全使它工作。这种方法的问题在于,实际地址在矢量中,而我用来过滤或选择的“类型”字段在子列表中。

我能形容的最好方式是这样的- 列表<-c(长地址),c(短地址),类型(LIST(街道编号,路线,县等))

很显然,我是一个初学者。我知道有一种更简单的方法,但是我真的在列表中苦苦挣扎,R似乎在大量使用它们。

编辑: 我绝对知道我无法保留整个清单。我需要拉出特定元素并将其绑定。我认为问题的很大一部分是,我对索引编制和操作列表没有很好的了解。

这里有一些地址可以尝试-“美国威斯康星州53934友谊市亚当斯街301号”具有7X3“地址组件”和相应的“类型”列表(共7个)。与“ 222 S Walnut St,Appleton,WI”进行比较45911,美国”,其地址成分为9X3,“类型”列表为9。类型列表需要重新连接到地址成分矩阵,因为类型列表标识了地址成分矩阵的每一行所包含的内容。

然后,不完全匹配会带来更多的复杂性。尝试使用“ 211大大道,罗斯柴尔德,威斯康星州54474”,您将获得2个列表,一个列表为东大大道,一个列表为西大大道。 Google似乎更喜欢东部,因为这就是“格式化地址”中显示的内容。我不在乎使用哪个,因为两个县都一样。有趣的是,“位置”包含2组地理编码,大概是指这两个匹配项。我认为这种复杂性可以忽略,因为由两个坐标组成的位置仍存储为“双精度”(而不是列表!),因此它应该与其他地址的坐标堆叠在一起。

编辑:这应该确实起作用,但是我在函数的do.call(rbind,types)行中遇到错误。

geocodes<-lapply(seq_along(res),function(x) {
  coordinates<-res[[x]]$results$geometry$location
  types<-res[[x]]$results$address_components[[1]]$types
  types<-do.call(rbind,types)
  types<-types[,1]
  address<-as.data.frame(res[[x]]$results$address_components[[1]]$long_name,strings.As.Factors=FALSE)
  names(address)[1]<-"V2"
  address<-cbind(address,types)
  address<-tidyr::spread(address,types,V2)
  address<-cbind(address,coordinates)
})

R表示“类型”对象不是列表,因此无法进行绑定。我尝试将其强制到列表,但仍然收到错误。我使用以下配对功能进行了检查,发现#294为空。这将停止功能。我收到“超出查询限制”的错误消息,但没有超过查询限制。

geocodes<-lapply(seq_along(res),function(x) {
  types<-res[[x]]$results$address_components[[1]]$types
  print(typeof(types))
})

2 个答案:

答案 0 :(得分:1)

这是我使用tidyverse函数的解决方案。这将获取地理编码以及格式化的地址(如果需要的话)(结果的其他部分也可以返回,只需将它们添加到要返回的地图函数的最后一行的表中即可。

suppressPackageStartupMessages(require(tidyverse))
suppressPackageStartupMessages(require(googleway))

set_key("your key here")

df <- tibble(full_address = c("2379 ADDISON BLVD HIGH POINT 27262", 
                                      "1751 W LEXINGTON AVE HIGH POINT 27262", "dljknbkjs"))

df %>% 
  mutate(geocode_result = map(full_address, function(full_address) {
    res <- google_geocode(full_address) 

    if(res$status == "OK") {

      geo <- geocode_coordinates(res) %>% as_tibble()

      formatted_address <- geocode_address(res)

      geocode <- bind_cols(geo, formatted_address = formatted_address)
    }
    else geocode <- tibble(lat = NA, lng = NA, formatted_address = NA)

    return(geocode)

  })) %>%
  unnest()
#> # A tibble: 3 x 4
#>   full_address                  lat   lng formatted_address                
#>   <chr>                       <dbl> <dbl> <chr>                            
#> 1 2379 ADDISON BLVD HIGH POI…  36.0 -80.0 2379 Addison Blvd, High Point, N…
#> 2 1751 W LEXINGTON AVE HIGH …  36.0 -80.1 1751 W Lexington Ave, High Point…
#> 3 dljknbkjs                    NA    NA   <NA>

reprex package(v0.2.1)于2019-04-14创建

答案 1 :(得分:0)

好的,我自己回答。

从地址数据帧开始。我将其称为“地址”,而数据框中的单数列也称为“地址”(请注意,我将其大写)。

使用googleway获取地理编码数据。我使用apply来遍历地址数据帧中的行

library(googleway)

    res<-apply(addresses,1,function (x){
      google_geocode(address=x[['Address']], key='insert your google api key here - its free to get')  
    })

这是我编写的将嵌套列表放入数据框的函数。

geocodes<-lapply(seq_along(res),function(x) {
  coordinates<-res[[x]]$results$geometry$location
  types<-res[[x]]$results$address_components[[1]]$types
  types<-do.call(rbind,types)
  types<-types[,1]
  address<-as.data.frame(res[[x]]$results$address_components[[1]]$long_name,strings.As.Factors=FALSE)
  names(address)[1]<-"V2"
  address<-cbind(address,types)
  address<-tidyr::spread(address,types,V2)
  address<-cbind(address,coordinates)
  })

library(data.table)
geocodes<-rbindlist(geocodes,fill=TRUE)

lapply沿着列表中的项目循环,在函数中,我创建了一个坐标数据框,并将地理编码放在此处。我还需要其他地址组成部分,尤其是县,所以我还创建了“类型”数据框,用于标识地址中的内容。我将地址项与类型绑定在一起,然后使用tidyr包中的spread将数据框重整为宽格式,使其只有1行宽。然后,我从坐标数据框中绑定纬度和经度。

rbindlist将其全部堆叠在一起。您可以使用do.call(rbind, geocodes),但是rbindlist更快。