如何使用R语言查找距离给定经纬度坐标最近的道路?

3

我有一个不同地点的几百个纬度-经度坐标对列表。我的目标是使用R获得从“家”到每个坐标对的驾车时间估计。

我已经在R中使用googleway包取得了一些成功,但是(可以预见的)当坐标位于远离公路的位置时,例如山顶处的坐标,就会遇到问题。在这些情况下,我希望能够估算出到每个有问题的坐标对最近道路的驾车时间。

为了说明,假设我的家庭位置是:

home <- "Edinburgh, UK"

...以及我想要查找驾车时间的位置示例数据框可能是;

location <- c("place_a", "place_b", "place_c") 
latitude <- c("56.87034", "57.69380", "57.36243")
longitude <- c("-4.199001", "-5.128715", "-5.104728")

df <- data.frame(location, latitude, longitude) 

我可以使用类似以下的方法获取地点A之间的距离/时间等信息,以及地点B之间的信息;

(注意:您需要自己拥有Google Maps API密钥才能复制此部分...)

library(googleway)
api_key <- [insert your Google Maps api key here!]

results <- google_distance(origins = home,
                  destinations = list(c("56.87034,-4.199001"),
                                      ("57.69380,-5.128715")),
                  mode = "driving",
                  key = api_key,
                  units = "imperial")

我使用以下方式获取所需数据:

results$rows[[1]]

然而,当我们尝试获取place_c的坐标时,会遇到问题,返回ZERO_RESULTS

results2 <- google_distance(origins = home,
              destinations = ("57.36243,-5.104728"),
              mode = "driving",
              key = api_key,
              units = "imperial")

我认为问题在于这些坐标是山上的中间位置,所以在这种情况下,我想要找到最近的道路而不是坐标。我希望能够通过googlewaynearest_road函数来解决问题,但似乎无法使其正常工作,例如以下代码无法正常运行;

df_points <- read.table(text = "lat lon
                     57.36243 -5.104728", header = T)

nearest_road <- google_nearestRoads(df_points, key = api_key)

有人能指导一下这里的问题吗?或者建议一个更好的解决方案?

非常感谢。


我只能猜测它离道路太远了,无法找到一条。我不得不将坐标移动到57.14743 -5.054728才能使其工作。我在谷歌文档中也没有看到关于它必须靠近道路多近的说明。另一种方法可能是找到苏格兰道路的形状文件并使用地理空间操作,而不是使用谷歌的API。 - SymbolixAU
感谢@SymbolixAU的帮助。最终我通过以下有用的帖子和使用googlewaygoogle_distance函数来替代gmapsdistance,解决了错误问题。 - monkeytennis
1个回答

1

我正在开发一个名为spaceheater的包,用于解决这个问题,并很快将在github上发布。与此同时:

我建议您下载Open Street Maps的地图文件,例如对于尼日利亚,请从geofabrik下载:http://download.geofabrik.de/africa/nigeria.html

根据monkeytennis的建议进行了编辑(感谢!):

library(sp)
library(rgdal)
library(raster)
library(googleway)
library(geosphere)
library(foreach)
###I did Nigeria because I have it in my file downloaded, you would use UK###
roadshp <- readOGR(dsn="nigeria-latest-free.shp", 
layer="gis.osm_roads_free_1")
#Isolate primary roads (or secondary and tertiary) if you wish#
roads <- roadshp[roadshp$fclass %in% c("primary", "secondary", "tertiary"),]
#Use SpatialPoints for your gps coords
location <- c("place_a", "place_b", "place_c")
latitude <- c(8.641, 10.892, 11.797)
longitude <- c(6.0046, 11.146, 5.477)
df <- data.frame(location, latitude, longitude)
coordinates(df)=~longitude+latitude
sp1 <- SpatialPoints(df)
proj4string(sp1)=CRS("+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84
                 +towgs84=0,0,0")
clodist <- dist2Line(sp1, roads)
df <- as.data.frame(df)
df$clodist <- clodist[,c("distance")]
df$lat <- clodist[,c("lat")]
df$lon <- clodist[,c("lon")]
iters <- nrow(df)
origin <- as.character("9.056, 7.497")
gc1 <- data.frame(round(df[,c("lat")],3), round(df[,c("lon")],3))
colnames(gc1) <- c("lat","lon")
df$lat <- as.character(gc1$lat)
df$lon <- as.character(gc1$lon)
gt2 <- paste(df[,c("lat")], df[,c("lon")], sep=",")
results <- google_distance(origins =origin, destinations= gt2,
            mode="driving",
            key="Your API Key Here")
results <-unlist(results)
results <- as.data.frame(results)
ttt <- head(results,-1)
ttt <- ttt[-c(iters+1), ]
m1 <- matrix(ttt, ncol=iters, byrow=TRUE)
distance <- as.data.frame(m1)
rownames(distance) <- c("Address", "DistanceKM", 
"DistanceM","TimeTextLow","TimeSecondsLow","TimeTextHigh","TimeSecondsHigh", 
"Status")

谢谢@Neal!这需要很多努力,非常有帮助,非常感激。我的老笔记本电脑花了一整天时间完成clodist <- dist2Line(sp1, roads)这行代码,但最终我成功了。我对上面的一个更改是将googlewaygoogle_distance替换为gmapsdistance代码块。原始代码抛出了一个错误:Error in rowXML[[dur]] : subscript out of bounds。似乎这是一个常见问题,但我无法解决它。我会关注你的spaceheater包。 - monkeytennis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接