2015-04-03 2 views
4

Извините, что это будет вопрос для цикла 101. Я изо всех сил, чтобы написать простой цикл для генерации таблицы расстояний между городами на основе данных широты долготыИспользование простого цикла для пространственных данных

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

местоположения возвращает следующую таблицу:

 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 

Моя цель в этой конкретной части задача состоит в том, чтобы создать таблицу расстояний (в километрах) между каждым из городов в характере корреляционной матрицы, причем диагональ равна 0 (т. е. все города на нулевом расстоянии от себя).

Для этого я использую пакет SP, который требует матрицы длиной однолатовых значений, так что я могу удалить текст следующим образом:

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

spDistsN1 инструмента позволяет мне получить эту информацию сравнивая расстояние, все города в матрице из одного отдельного города. Очевидно, что я могу использовать следующее выражение для получения расстояний всех городов из Шеффилда (город или строка # 1):

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

Это правильно дает:

[1] 0.000 9591.009 1329.882 5436.133 

Однако, чтобы достичь своей желаемой корреляции матрица вывода стиль, я хочу, чтобы добиться этого для каждого из городов, поэтому я попытался написать цикл:

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

Это дает мне правильные значения для Нью-Йорка:

[1] 5436.133 12967.023 6697.541  0.000 

Таким образом, я полагаю, что я переписал один город другим во время цикла. Я ценю помощь в том, чтобы показать мне, где я ошибаюсь. Большое спасибо.

ответ

4

Сначала объявить матрицу и использовать итератор i, чтобы указать строку для заполнения:

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 

Результаты

> 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

Я не уверен, если это то, что вы ищете для

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 

Результаты

 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 
+0

Все ответы здесь действительно полезны. Доминику легче всего понять, основываясь на моих мысленных процессах. «apply» - это элегантное решение благодаря Dimitris, и Nicola я проверю этот пакет, хотя, как вы, вероятно, можете сказать по моим попыткам, выходить за рамки 2D-мышления может занять некоторое время! – RichS

1

Вы можете попробовать функцию distm из geosphere пакета:

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 

Он возвращает расстояние в метрах и учитывает геометрию Земли.

+0

да, но предполагает, что земля - ​​это сфера; 'sp :: spDistsN1' предполагает, что это эллипсоид (WGS84). –