使用 googleway 在 R 中进行地理编码
Geocoding in R using googleway
我已阅读Batch Geocoding with googleway R
我正在尝试使用 google 方式对一些地址进行地理编码。我想要返回地理编码、地址和县。
使用上面链接的答案,我创建了以下函数。
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 返回的多个匹配结果(在我的列表中似乎成为一对)。重点是,从一个文件中获取地址并从另一个文件中获取坐标似乎相当鲁莽,而且由于无论如何我都需要县,所以我需要一种方法将其从 google 保存在 'res' 中的结果列表中提取出来.
问题是某些地址的 "types" 比其他地址多,这意味着像我上面那样按行引用不起作用。
我还尝试在函数中包含 rbindlist 以将子列表转换为数据表,然后提取字段,但无法完全正常工作。这种方法的问题是实际地址在向量中,但我用来过滤的 'types' 字段或 select 在子列表中。
我能描述的最好的方式是这样的 -
list <- c(long address),c(short address), types(LIST(街道号码,路线,县城等))
显然,我是这方面的初学者。我知道有一种更简单的方法,但我真的很难处理列表,而 R 似乎广泛使用了它们。
编辑:
我绝对认识到我不能 rbind 整个列表。我需要拉出特定元素并仅绑定这些元素。在我看来,问题的很大一部分是我没有很好地处理索引和操作列表。
这里有一些地址可供尝试 - “301 Adams St, Friendship, WI 53934, USA”有一个 7X3 "address components" 和相应的 "types" 列表 7。将其与“222 S Walnut”进行比较St, Appleton, WI 45911, USA”,其地址分量为 9X3,"types" 列表为 9。类型列表需要连接回地址分量矩阵,因为类型列表标识了地址的每一行组件矩阵包含。
然后,不完美的匹配会带来更多的复杂性。尝试“211 Grand Avenue, Rothschild, WI, 54474”,您会得到 2 个列表,一个用于 east grand ave,一个用于 west grand ave。 Google 似乎更喜欢东部,因为那是 "formatted address." 中出现的东西,我真的不在乎使用哪个,因为两者的县都是相同的。有趣的是 "location" 包含 2 组地理编码,大概是指这两个匹配项。我认为可以忽略这种复杂性,因为由两个坐标组成的位置仍存储为 'double'(不是列表!),因此它应该与其他地址的坐标堆叠在一起。
编辑:这应该确实有效,但我在函数的 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 表示 "types" 对象不是列表,因此无法对其进行绑定。我尝试将它强制到列表中,但仍然出现错误。我使用以下成对的向下函数进行了检查,发现#294 为空。这将停止该功能。我收到 "over query limit" 作为错误,但我没有超过查询限制。
geocodes<-lapply(seq_along(res),function(x) {
types<-res[[x]]$results$address_components[[1]]$types
print(typeof(types))
})
好的,我会自己回答的。
从地址数据框开始。我将我的命名为 "addresses",数据框中的单数列也称为 "Addresses"(请注意,我将其大写)。
使用 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 沿着列表中的项目循环,在函数中我创建了一个坐标数据框并将地理编码放在那里。我还想要其他地址组件,尤其是县,所以我还创建了 "types" 数据框,用于标识地址中的项目。我将地址项与类型绑定,然后使用 tidyr 包中的 spread 将数据框重塑为宽格式,因此它只有 1 行宽。然后我从坐标数据框中 cbind 纬度和经度。
rbindlist 将它们全部堆叠在一起。您可以使用 do.call(rbind, geocodes)
但 rbindlist 更快。
这是我使用 tidyverse 函数的解决方案。这将获取地理编码以及格式化地址,以备不时之需(结果的其他组成部分也可以返回,只需将它们添加到返回的地图函数最后一行的 table .
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 创建
我已阅读Batch Geocoding with googleway R
我正在尝试使用 google 方式对一些地址进行地理编码。我想要返回地理编码、地址和县。
使用上面链接的答案,我创建了以下函数。
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 返回的多个匹配结果(在我的列表中似乎成为一对)。重点是,从一个文件中获取地址并从另一个文件中获取坐标似乎相当鲁莽,而且由于无论如何我都需要县,所以我需要一种方法将其从 google 保存在 'res' 中的结果列表中提取出来.
问题是某些地址的 "types" 比其他地址多,这意味着像我上面那样按行引用不起作用。
我还尝试在函数中包含 rbindlist 以将子列表转换为数据表,然后提取字段,但无法完全正常工作。这种方法的问题是实际地址在向量中,但我用来过滤的 'types' 字段或 select 在子列表中。
我能描述的最好的方式是这样的 - list <- c(long address),c(short address), types(LIST(街道号码,路线,县城等))
显然,我是这方面的初学者。我知道有一种更简单的方法,但我真的很难处理列表,而 R 似乎广泛使用了它们。
编辑: 我绝对认识到我不能 rbind 整个列表。我需要拉出特定元素并仅绑定这些元素。在我看来,问题的很大一部分是我没有很好地处理索引和操作列表。
这里有一些地址可供尝试 - “301 Adams St, Friendship, WI 53934, USA”有一个 7X3 "address components" 和相应的 "types" 列表 7。将其与“222 S Walnut”进行比较St, Appleton, WI 45911, USA”,其地址分量为 9X3,"types" 列表为 9。类型列表需要连接回地址分量矩阵,因为类型列表标识了地址的每一行组件矩阵包含。
然后,不完美的匹配会带来更多的复杂性。尝试“211 Grand Avenue, Rothschild, WI, 54474”,您会得到 2 个列表,一个用于 east grand ave,一个用于 west grand ave。 Google 似乎更喜欢东部,因为那是 "formatted address." 中出现的东西,我真的不在乎使用哪个,因为两者的县都是相同的。有趣的是 "location" 包含 2 组地理编码,大概是指这两个匹配项。我认为可以忽略这种复杂性,因为由两个坐标组成的位置仍存储为 'double'(不是列表!),因此它应该与其他地址的坐标堆叠在一起。
编辑:这应该确实有效,但我在函数的 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 表示 "types" 对象不是列表,因此无法对其进行绑定。我尝试将它强制到列表中,但仍然出现错误。我使用以下成对的向下函数进行了检查,发现#294 为空。这将停止该功能。我收到 "over query limit" 作为错误,但我没有超过查询限制。
geocodes<-lapply(seq_along(res),function(x) {
types<-res[[x]]$results$address_components[[1]]$types
print(typeof(types))
})
好的,我会自己回答的。
从地址数据框开始。我将我的命名为 "addresses",数据框中的单数列也称为 "Addresses"(请注意,我将其大写)。
使用 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 沿着列表中的项目循环,在函数中我创建了一个坐标数据框并将地理编码放在那里。我还想要其他地址组件,尤其是县,所以我还创建了 "types" 数据框,用于标识地址中的项目。我将地址项与类型绑定,然后使用 tidyr 包中的 spread 将数据框重塑为宽格式,因此它只有 1 行宽。然后我从坐标数据框中 cbind 纬度和经度。
rbindlist 将它们全部堆叠在一起。您可以使用 do.call(rbind, geocodes)
但 rbindlist 更快。
这是我使用 tidyverse 函数的解决方案。这将获取地理编码以及格式化地址,以备不时之需(结果的其他组成部分也可以返回,只需将它们添加到返回的地图函数最后一行的 table .
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 创建