问题
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