簡體   English   中英

R(或Python)是否可以加快地理空間分析?

[英]R (or Python) any way to speed up geospatial analysis?

我正在研究一個我要確定彼此之間距離不遠的數據點的性質的問題。 基本上,對於每一行數據,我都會嘗試確定地理范圍內數據點的“鄰域”,然后找出該“鄰域”的特征。

問題是這是O ^ 2問題,因為我當前嵌套了for循環,這意味着我正在運行nrow ^ 2計算(我有70k行,所以是4.9B!計算....哎呀)

所以我的R(偽)代碼是

for (i in 1:n.geopoints) {
   g1<-df[i,]
   for (j in 1:n.geopoints) {
      g2 <- df[j,]
      if (gdist(lat.1 = g1$lat, lon.1=g1$lon, lat.2 = g2$lat, lon.2 = g2$lon, units = "m") <= 1000) {
         [[[DO SOME STUFFF]]]
      }
   }
}

如何以更直接的方式實現這一目標? 有我可以依靠的功能嗎? 我可以向量化嗎?

我在R中有此功能,但是如果有更好的功能可用,則可以輕松地將其放到Python中。

謝謝

這是一種使用data.table的方法,以及我為該問題編寫的重寫的data.table公式,以便它可以在data.table操作中使用

這個想法是在每個單點,每個單點上執行一個data.table連接,但是在連接內計算每對點之間的距離,並刪除閾值之外的點。 這是受@Jaap出色回答的啟發

設定

Haversine公式是

## Haversine formula
dt.haversine <- function(lat_from, lon_from, lat_to, lon_to, r = 6378137){
  radians <- pi/180
  lat_to <- lat_to * radians
  lat_from <- lat_from * radians
  lon_to <- lon_to * radians
  lon_from <- lon_from * radians
  dLat <- (lat_to - lat_from)
  dLon <- (lon_to - lon_from)
  a <- (sin(dLat/2)^2) + (cos(lat_from) * cos(lat_to)) * (sin(dLon/2)^2)
  return(2 * atan2(sqrt(a), sqrt(1 - a)) * r)
}

我在此示例中使用的數據來自我的googleway包,它是墨爾本City Loop電車上的電車站

library(googleway)

## Tram stops data
head(tram_stops)
#   stop_id                                     stop_name stop_lat stop_lon
# 1   17880           10-Albert St/Nicholson St (Fitzroy) -37.8090 144.9731
# 2   17892    10-Albert St/Nicholson St (East Melbourne) -37.8094 144.9729
# 3   17893 11-Victoria Pde/Nicholson St (East Melbourne) -37.8083 144.9731
# 4   18010    9-La Trobe St/Victoria St (Melbourne City) -37.8076 144.9709
# 5   18011  8-Exhibition St/La Trobe St (Melbourne City) -37.8081 144.9690
# 6   18030    6-Swanston St/La Trobe St (Melbourne City) -37.8095 144.9641

計算

現在我們有數據,並且距離公式,我們可以構建data.table加盟

library(data.table)

## set the tram stop data as a data.table
dt1 <- as.data.table(tram_stops)

## add a column that will be used to do the join on
dt1[, joinKey := 1]

## find the dinstance between each point to every other point
## by joining the data to itself
dt2 <- dt1[
  dt1
  , {
    idx = dt.haversine(stop_lat, stop_lon, i.stop_lat, i.stop_lon) < 500 ## in metres
    .(stop_id = stop_id[idx],
      near_stop_id = i.stop_id)
  }
  , on = "joinKey"
  , by = .EACHI
]

結果

dt2現在包含兩列距離彼此相距500米以內的stop_id(包括相同的停靠點,因此可以將其刪除)

dt2 <- dt2[stop_id != near_stop_id]

情節

當我們使用googleway ,讓我們繪制一些結果(要做到這一點,您需要一個Google Maps API密鑰,或使用另一個映射庫,例如傳單)

mapKey <- "your_api_key"

## Just pick one to look at
myStop <- 18048
dt_stops <- dt3[stop_id == myStop ]

## get the lat/lons of each stop_id
dt_stops <- dt_stops[
  dt1      ## dt1 contains the lat/lons of all the stops
  , on = c(near_stop_id = "stop_id")
  , nomatch = 0
]

google_map(key = mapKey) %>%
  add_circles(data = dt1[stop_id == myStop], lat = "stop_lat", lon = "stop_lon", radius = 500) %>%
  add_markers(dt_stops, lat = "stop_lat", lon = "stop_lon")

在此處輸入圖片說明

筆記

data.table應該非常有效,但是顯然我在這里使用的數據只有51行。 您必須讓我知道此方法可擴展到您的數據的程度

您可能需要考慮其他方法。 我會使用QGIS之類的GIS工具來細分您的數據。 就像您說的那樣,您不需要數據的完整笛卡爾連接,只需本地集群即可。 查看一些聚類問題。

GIS Stackexchange上的這個問題通過一個具有800k數據點的類似類型問題解決。 https://gis.stackexchange.com/questions/211106/clustering-points-polygons-based-on-proximity-within-specifed-distance-using-q

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM