Using a simple for loop on spatial data

﹥>﹥吖頭↗ 提交于 2020-01-03 15:38:01

问题


I'm sorry this is going to be a for loop 101 question. I am struggling to write a simple for loop to generate a table of distances between cities based upon longitude-latitude data

locations <-read.csv("distances.csv")

locations returns the following table:

       City Type       long      lat
1 Sheffield  EUR  -1.470085 53.38113
2        HK WRLD 114.109497 22.39643
3    Venice  EUR  12.315515 45.44085
4  New York WRLD -74.005941 40.71278

My goal in this particular part of the task is to produce a table of the distances (in kilometres) between each of the cities in the nature of a correlation matrix, with the diagonal being 0 (ie all cities are zero distance from themselves).

To do this I am using the sp package, which requires a matrix of long-lat values, so I can remove the text as follows:

datmax <- data.matrix(locations)
datmax2 <- datmax[,-1:-2]

The tool spDistsN1 allows me to get this information by comparing the distance all cities in the matrix are from one individual city. Clearly, I can use the following expression to obtain the distances of all cities from Sheffield (city or row# 1):

km <- spDistsN1(datmax2, datmax2[1,], longlat=TRUE)

This correctly gives:

[1]    0.000 9591.009 1329.882 5436.133

However, to achieve my desired correlation matrix style output, I want to achieve this for each of the cities, so I tried to write a for loop:

for (i in 1:nrow(datmax2)){
  kmnew <- spDistsN1(datmax2, datmax2[i,], longlat=TRUE)
}

This gives me the correct values for NY:

[1]  5436.133 12967.023  6697.541     0.000

So I presume I have overwritten one city by another throughout the loop. I appreciate the help in showing me where I am going wrong. Many thanks.


回答1:


First declare a matrix and use your iterator i to indicate the row to be filled in:

kmnew <- matrix(NA, nrow=4, ncol=4)
for (i in 1:nrow(datmax2)){
  kmnew[i,] <- spDistsN1(datmax2, datmax2[i,], longlat=TRUE)
}

colnames(kmnew) <- locations$City
rownames(kmnew) <- locations$City

Results

> kmnew

          Sheffield        HK   Venice  New York
Sheffield     0.000  9591.009 1329.882  5436.134
HK         9591.009     0.000 9134.698 12967.024
Venice     1329.882  9134.698    0.000  6697.541
New York   5436.134 12967.024 6697.541     0.000



回答2:


I am not sure if this is what you are looking for

library(sp)

# Provide data for reproducibility
locations <- data.frame(City=c("Sheffield", "HK", "Venice", "New York"),
                    Type=c("EUR", "WRLD", "EUR", "WRLD"),
                    long=c(-1.470085, 114.109497, 12.315515, -74.005941),
                    lat=c(53.38113, 22.39643, 45.44085, 40.71278))

km <- apply(as.matrix(locations[, c(-1, -2)]), 1, function(x){
  spDistsN1(as.matrix(locations[, c(-1, -2)]), x, longlat=TRUE)
})

km <- data.frame(locations[, 1],  km)
names(km) <- c("City", as.character(locations[, 1]))
km

Results

       City Sheffield        HK   Venice  New York
1 Sheffield     0.000  9591.009 1329.882  5436.134
2        HK  9591.009     0.000 9134.698 12967.024
3    Venice  1329.882  9134.698    0.000  6697.541
4  New York  5436.134 12967.024 6697.541     0.000



回答3:


You can try the distm function from the geosphere package:

 distm(datmax2)
 #        [,1]     [,2]    [,3]     [,4]
 #[1,]       0  9586671 1329405  5427956
 #[2,] 9586671        0 9130036 12962132
 #[3,] 1329405  9130036       0  6687416
 #[4,] 5427956 12962132 6687416        0

It returns the distance in meters and takes into account the geometry of the earth.



来源:https://stackoverflow.com/questions/29430303/using-a-simple-for-loop-on-spatial-data

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!