#r
#r
Вопрос:
У меня есть два списка, один содержит id
и для каждого id
набор координат:
------- ------ ------
| store | lat | lon |
------- ------ ------
| 123 | 37.2 | 13.5 |
| 456 | 39.1 | 9.1 |
| 789 | 45.4 | 11.0 |
------- ------ ------
В то время как вторая представляет собой список метеостанций с координатами и некоторыми другими данными:
---- -------- -------- --------------- ----------------
| id | lat | lon | name | address |
---- -------- -------- --------------- ----------------
| 1 | 44.907 | 8.612 | airport_one | bond street |
| 2 | 39.930 | 9.720 | airport_two | oxford street |
| 3 | 40.020 | 15.280 | airport_three | ellesmere road |
---- -------- -------- --------------- ----------------
Я хотел бы добавить два столбца в первый список (список магазинов) с расстоянием и названием ближайшего аэропорта, поэтому мне нужно сравнить каждый магазин с каждым аэропортом и вернуть кратчайшее расстояние.
Я пытался достичь этого в цикле for, используя distm
функцию, но я определенно что-то теряю:
for (val in 1:length(airport_master[,1])){
n <- distm(store_master[1,3:2], airport_master[val,6:5])
distances <- append(distances, n)
store_master$closest_airport <- airport_master$name[val])
}
Есть ли какая-либо библиотека или лучший способ достичь этого результата?
Ответ №1:
Вы можете сделать это следующим образом, используя tidyverse
пакет:
library(tidyverse)
# data
store_master <-
tibble(
'store' = c(123, 456, 789),
'lat' = c(37.2, 39.1, 45.4),
'lon' = c(13.5, 9.1, 11.0)
)
airport_master <-
tibble(
'id' = 1:3,
'lat' = c(44.907, 39.93, 40),
'lon' = c(8.612, 9.72, 15.28),
'name' = c('airport_one', 'airport_two', 'airport_three')
)
# solution
crossing(
store = store_master$store,
id = airport_master$id
) %>%
left_join(store_master, "store") %>%
left_join(airport_master, "id", suffix = c("_store", "_airpot")) %>%
mutate(distance = sqrt((lat_store - lat_airpot)^2 (lon_store - lon_airpot)^2)) %>%
group_by(store) %>%
filter(distance == min(distance))
Результат:
store id lat_store lon_store lat_airpot lon_airpot name distance
<dbl> <int> <dbl> <dbl> <dbl> <dbl> <chr> <dbl>
1 123 3 37.2 13.5 40 15.3 airport_three 3.32
2 456 2 39.1 9.1 39.9 9.72 airport_two 1.04
3 789 1 45.4 11 44.9 8.61 airport_one 2.44
Ответ №2:
В моем решении использовалась функция pdist из библиотеки pdist
### Store
library(pdist)
dat1 <- cbind('store' = c(123, 456, 789),
'lat' = c(37.2, 39.1, 45.4),
'lon' = c(13.5, 9.1, 11.0))
dat2 <- cbind('id' = 1:3,
'lat' = c(44.907, 39.93, 40),
'lon' = c(8.612, 9.72, 15.28))
dist.mat <- as.matrix(pdist(dat1[, 2:3], dat2[,2:3]))
dat2[apply(dist.mat, 1, which.min), 1] ## Or name
### Combining the result with the first data set
data.frame(dat1,
'ClosestID' = dat2[apply(dist.mat, 1, which.min), 1])
Комментарии:
1. Большое спасибо, но как я могу создать столбец в da2 с именем?
2. Просто измените столбец, взятый в качестве имени. Для связывания столбцов вместе использовался либо cbind, либо data.frame.
3. Я совсем новичок в R, не могли бы вы, пожалуйста, показать мне пример?