2017-02-14 121 views
0

我有兩個單獨但相關的問題。使用gDistance rgeos查找兩個SpatialPointsDataframes之間的最近距離?

首先,我想確定subset_original_data.csv文件中每個數據點到最近的建築工地的距離(construction_layer.csv)。我試圖用gDistance()函數計算最近的鄰居,但我也接受其他想法。

我想附加我的subset_original_data.csv數據幀與這個從construction_layer.csv最近鄰距離的新向量。也就是說,對於我的subset_original_data.csv數據幀的每一行,我都希望到最近的建築工地的最小距離。

第二個目標是確定從每個subset_original_data.csv行到高速公路shapefile(fwy.shp)的最近距離。我還想將這個新的矢量附加到subset_original.csv數據框中。

我已成功將construction_layer.csvsubset_original_data.csv轉換爲SpatialPointsDataFrame。我還通過使用readOGR()函數讀取形狀文件,將fwy.shp文件轉換爲SpatialLinesDataFrame。我不確定下一步該去哪裏。非常感謝您的意見!

〜$ spacedSparking

這裏是我的數據: construction_layer.csvfwy.shpsubset_original_data.csv

這裏是我的代碼:

#requiring necessary packages: 
library(rgeos) 
library(sp) 
library(rgdal) 

#reading in the files: 
mydata <- read.csv("subset_original_data.csv", header = T) 
con <- read.csv("construction_layer.csv", header = T) 
fwy <- readOGR(dsn = "fwy.shp") 

#for those who prefer not to download any files: 
data.lat <- c(45.53244, 45.53244, 45.53244, 45.53244, 45.53245, 45.53246) 
data.lon <- c(-122.7034, -122.7034, -122.7034, -122.7033, -122.7033, -122.7032) 
data.black.carbon <- c(187, 980, 466, 826, 637, 758) 
mydata <- data.frame(data.lat, data.lon, data.black.carbon) 

con.lat <- c(45.53287, 45.53293, 45.53299, 45.53259, 45.53263, 45.53263) 
con.lon <- c(-122.6972, -122.6963, -122.6952, -122.6929, -122.6918, -122.6918) 
con <- data.frame(con.lat, con.lon) 

#I am not sure how to include the `fwy.shp` in a similar way, 
#so don't worry about trying to solve that problem if you would prefer not to download the file. 

#convert each file to SpatialPoints or SpatialLines Dataframes: 
mydata.coords <- data.frame(lon = mydata[,2], lat = mydata[,1], data = mydata) 
mydata.sp <- sp::SpatialPointsDataFrame(mydata.coords, data = data.frame(BlackCarbon = mydata[,3])) #appending a vector containing air pollution data 

con.coords <- data.frame(lon = con[,2], lat = con[,1]) 
con.sp <- sp:SpatialPointsDataFrame(con.coords, data = con) 

str(fwy) #already a SpatialLinesDataFrame 

#Calculate the minimum distance (in meters) between each observation between mydata.sp and con.sp and between mydata.sp and fwy objects. 

#Create a new dataframe appending these two nearest distance vectors back to the original mydata file. 

#Desired output: 
head(mydata.appended) 
    LATITUDE LONGITUDE BC6. NEAREST_CON (m) NEAREST_FWY (m) 
1 45.53244 -122.7034 187 ???    ??? 
2 45.53244 -122.7034 980 ???    ??? 
3 45.53244 -122.7034 466 ???    ??? 
4 45.53244 -122.7033 826 ???    ??? 
5 45.53245 -122.7033 637 ???    ??? 
6 45.53246 -122.7032 758 ???    ??? 

編輯:

解決方案: 如果有疑問,請問一個朋友誰是R嚮導!他甚至製作了一張地圖。

library(rgeos) 
library(rgdal) 
library(leaflet) 
library(magrittr) 

#Define Projections 
wgs84<-CRS("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs +towgs84=0,0,0") 
utm10n<-CRS("+proj=utm +zone=10 +ellps=GRS80 +datum=NAD83 +units=m +no_defs +towgs84=0,0,0") 

#creating example black carbon data by hand: 
lat <- c(45.5324, 45.5325, 45.53159, 45.5321, 45.53103, 45.53123) 
lon <- c(-122.6972, -122.6963, -122.6951, -122.6919, -122.6878, -122.6908) 
BlackCarbon <- c(187, 980, 466, 826, 637, 758) 
bc.coords <- data.frame(lat, lon, BlackCarbon) 
bc<-SpatialPointsDataFrame(data.frame(x=lon,y =lat),data=data.frame(BlackCarbon),proj4string = wgs84) 

# Project into something - Decimal degrees are no fun to work with when measuring distance! 
bcProj<-spTransform(bc,utm10n) 

#creating example construction data layer: 
con.lat <- c(45.53287, 45.53293, 45.53299, 45.53259, 45.53263, 45.53263) 
con.lon <- c(-122.6972, -122.6963, -122.6952, -122.6929, -122.6918, -122.6910) 
con.coords <- data.frame(con.lat, con.lon) 
con<-SpatialPointsDataFrame(data.frame(x=con.lon,y =con.lat),data=data.frame(ID=1:6),proj4string = wgs84) 
conProj<-spTransform(con,utm10n) 

#All at once (black carbon points on top, construction on the y-axis) 
dist<-gDistance(bcProj,conProj,byid=T) 

min_constructionDistance<-apply(dist, 2, min) 

# make a new column in the WGS84 data, set it to the distance 
# The distance vector will stay in order, so just stick it on! 
[email protected]$Nearest_Con<-min_constructionDistance 
[email protected]$Near_ID<-as.vector(apply(dist, 2, function(x) which(x==min(x)))) 

#Map the original WGS84 data 
pop1<-paste0("<b>Distance</b>: ",round(bc$Nearest_Con,2),"<br><b>Near ID</b>: ",bc$Near_ID) 
pop2<-paste0("<b>ID</b>: ",con$ID) 
m<-leaflet()%>% 
    addTiles()%>% 
    addCircleMarkers(data=bc,radius=8,fillColor = 'red',fillOpacity=0.8,weight=1,color='black',popup=pop1)%>% 
    addCircleMarkers(data=con,radius=8,fillColor = 'blue',fillOpacity=0.8,weight=1,color='black',popup=pop2) 
m 
+0

通常它更適合於你的問題,以創建一個示例數據集,而不是將其附着 - 我不能代表別人,但我並不熱衷於從未知來源 – SymbolixAU

+0

這是可以理解的下載文件。我會試着弄清楚如何在帖子中包含示例數據。 – spacedSparking

+0

您也可以使用內置的數據集,例如'sp'包中的meuse數據集:'data(「meuse」)' – SymbolixAU

回答

1

可以使用一個半正矢距離函數,並使用函數編程,以實現期望的結果。

library(geosphere) 
find_min_dist <- function(site, sites) { 
    min(distHaversine(site, sites)) 
} 
#X is the data id, split into a list so you can iterate through each site point 
data <- split(mydata[ , 3:2], mydata$X) 
sapply(data, find_min_dist, sites = con.coords) 
+0

感謝您向我介紹'geosphere'軟件包。我正在使用你正在使用的'mydata'對象。它是'mydata < - read.csv('subset_original_data.csv)',或'mydata < - data.frame(data.lat,data.lon,data.black.carbon)'? – spacedSparking

+0

另外,我不知道應該用什麼來代替'mydata $ X'參數。我假設它是'BC6.'變量,但是這給了我一個奇怪的輸出:'> head(data1) -773 -374 -288 -272 -212 -127 174.4300 229.2947 146。6889 204.5449 146.9234 132.5356' – spacedSparking

+0

X是我用你的代碼在你的csv中讀取時的行名。你只需要每行的ID和ID,這樣就可以將每個點分成一個列表並計算所有建築工地的距離。我也無法用你的代碼讀取形狀文件,但是一旦你從形狀文件中獲得了所有的經緯度對,它就是一樣的原理 – troh