Сопоставить два набора данных по минимальному геопространственному расстоянию (R) - PullRequest
0 голосов
/ 09 февраля 2019

У меня есть два следующих набора данных:

houses <- data.table(house_number = c(1:3),
                     lat_decimal = seq(1.1, 1.3, by = 0.1),
                     lon_decimal = seq(1.4, 1.6, by = 0.1))
stations <- data.table(station_numer = c(1:11),
                       lat_decimal = seq(1, 2, by = 0.1),
                       lon_decimal = seq(2, 3, by = 0.1))

Я хочу объединить houses и stations так, чтобы результирующая station_number была станцией, ближайшей к соответствующей house_number.

Этот вопрос очень похож на , но я не уверен, работают ли они с широтой и долготой, а также я не знаю, как рассчитать расстояния при работе с долготой иширота (именно поэтому я предпочитаю просто использовать distm из пакета geosphere).

Я никогда не работал с внешней функцией.Если ответ на вышеупомянутый вопрос будет работать, как я могу адаптировать ответ для использования функции distm вместо функции sqrt?

Ответы [ 2 ]

0 голосов
/ 09 февраля 2019

Используйте match_nrst_haversine из hutilscpp:

library(hutilscpp)
houses[, c("station_number", "dist") := match_nrst_haversine(lat_decimal,
                                                             lon_decimal,
                                                             addresses_lat = stations$lat_decimal,
                                                             addresses_lon = stations$lon_decimal,
                                                             Index = stations$station_numer,
                                                             close_enough = 0,
                                                             cartesian_R = 5)]

houses
#>    house_number lat_decimal lon_decimal station_number     dist
#> 1:            1         1.1         1.4              1 67.62617
#> 2:            2         1.2         1.5              1 59.87076
#> 3:            3         1.3         1.6              1 55.59026

Возможно, вы захотите настроить close_enough и cartesian_R, если ваши данные многочисленны (т. Е. Более миллиона точек для соответствия) для производительности.

`cartesian_R`

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

`close_enough`    

Расстояние в метрах, ниже которого будет считаться совпадение.(Расстояние, которое считается «достаточно близким» для совпадения.)

Например, close_enough = 10 означает, что первое местоположение в пределах десяти метров будет сопоставлено, даже если более близкое совпадение произойдет позже.

Может быть представлен в виде строки для выделения единиц, например close_enough = "0.25km".Допускаются только км и м.

0 голосов
/ 09 февраля 2019

Ваш вопрос немного сложнее простого слияния, а outer несколько не подходит для этой цели.Чтобы быть как можно более тщательным, мы хотим рассчитать расстояние между всеми комбинациями домов и станций, а затем оставить только ближайшую станцию ​​на дом.Нам понадобятся два пакета:

library(tidyverse)
library(geosphere)

Сначала немного подготовки.distm ожидает, что координаты будут упорядочены как первая долгота, вторая широта (у вас наоборот), так что давайте исправим это, назовем столбцы лучше и исправим опечатку, пока мы на нем:

houses <- data.frame(house_number = c(1:3),
                     lon_house = seq(1.4, 1.6, by = 0.1),
                     lat_house = seq(1.1, 1.3, by = 0.1)
                     )
stations <- data.frame(station_number = c(1:11),
                       lon_station = seq(2, 3, by = 0.1),
                       lat_station = seq(1, 2, by = 0.1)
                       )

Мы создадим «вложенные» фреймы данных, чтобы было проще хранить координаты вместе:

house_nest <- nest(houses, -house_number, .key = 'house_coords')
station_nest <- nest(stations, -station_number, .key = 'station_coords')

  house_number house_coords        
         <int> <list>              
1            1 <data.frame [1 × 2]>
2            2 <data.frame [1 × 2]>
3            3 <data.frame [1 × 2]>

   station_number station_coords      
            <int> <list>              
 1              1 <data.frame [1 × 2]>
 2              2 <data.frame [1 × 2]>
 3              3 <data.frame [1 × 2]>
 4              4 <data.frame [1 × 2]>
 5              5 <data.frame [1 × 2]>
 6              6 <data.frame [1 × 2]>
 7              7 <data.frame [1 × 2]>
 8              8 <data.frame [1 × 2]>
 9              9 <data.frame [1 × 2]>
10             10 <data.frame [1 × 2]>
11             11 <data.frame [1 × 2]>

Используйте dplyr::crossing для объединения каждой строки из обоих фреймов данных:

data.master <- crossing(house_nest, station_nest)

   house_number house_coords         station_number station_coords      
          <int> <list>                        <int> <list>              
 1            1 <data.frame [1 × 2]>              1 <data.frame [1 × 2]>
 2            1 <data.frame [1 × 2]>              2 <data.frame [1 × 2]>
 3            1 <data.frame [1 × 2]>              3 <data.frame [1 × 2]>
 4            1 <data.frame [1 × 2]>              4 <data.frame [1 × 2]>
 5            1 <data.frame [1 × 2]>              5 <data.frame [1 × 2]>
 6            1 <data.frame [1 × 2]>              6 <data.frame [1 × 2]>
 7            1 <data.frame [1 × 2]>              7 <data.frame [1 × 2]>
 8            1 <data.frame [1 × 2]>              8 <data.frame [1 × 2]>
 9            1 <data.frame [1 × 2]>              9 <data.frame [1 × 2]>
10            1 <data.frame [1 × 2]>             10 <data.frame [1 × 2]>
# ... with 23 more rows

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

data.dist <- data.master %>% 
  mutate(dist = map2_dbl(house_coords, station_coords, distm)) %>% 
  group_by(house_number) %>% 
  filter(dist == min(dist))

  house_number house_coords         station_number station_coords         dist
         <int> <list>                        <int> <list>                <dbl>
1            1 <data.frame [1 × 2]>              1 <data.frame [1 × 2]> 67690.
2            2 <data.frame [1 × 2]>              1 <data.frame [1 × 2]> 59883.
3            3 <data.frame [1 × 2]>              1 <data.frame [1 × 2]> 55519.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...