быстрый, правильный расчет расстояния - PullRequest
0 голосов
/ 25 января 2019

У меня большой фрейм данных (> 8 миллионов строк) с наблюдениями за отдельными людьми и различными сайтами.Мне интересно посмотреть на близость этих сайтов к нескольким ключевым точкам (1 место в 2014 году и 2 места в 2015 году).

Чтобы свести к минимуму количество вычислений (и ускорить процесс), я 'Мы использовали dplyr, чтобы свести все известные местоположения к одному репрезентативному сайту в каждом году, а затем попытались использовать функцию distGeo для вычисления расстояния, когда год совпадает.

dist <- df %>% 
  mutate(year = year(ts)) %>% #ts is the time stamp for each observation
  select(site, lat, lon, year) %>% 
  group_by(site, lat, lon, year) %>% 
  summarise(n=n()) %>% #if I stop after summarise, the data frame has been reduced to 93 observations
  mutate(dist1 = ifelse(year == "2014",
                        distGeo(c(-64.343043, 45.897932), #coordinates for key location in 2014
                                df[,c("lon", "lat")])/1000, 
                         NA_real_)) #I have a similar lines for the two key locations in 2015

Выполнение этой части требует~ 30 минут, и результат - расстояние 740,1656 км для каждого участка 2014 года.Как я могу исправить этот код, чтобы обеспечить правильное расстояние и, в идеале, ускорить вычисления?

РЕДАКТИРОВАТЬ:

Как показано ниже, вот решение:

dist <- df %>% 
  mutate(year = year(ts)) %>%
  select(site, lat, lon, year) %>% 
  group_by(site, lat, lon, year) %>% 
  summarise(n=n()) %>% 
  mutate(dist1 = ifelse(year == "2014",
                     pmap_dbl(list(lon, lat),
                              ~distVincentyEllipsoid(c(-64.343043, 45.897932), 
                                                     c(.x, .y))/1000), 
                     NA_real_)

1 Ответ

0 голосов
/ 25 января 2019

Вы можете использовать purrr::pmap, чтобы сделать это довольно быстро (так как distGeo не векторизовано) ...

library(tidyverse) #for dplyr and purrr
library(geosphere) #for distGeo

df <- data.frame(lat = 90*runif(100), lon = 90*runif(100)) #dummy data

dist <- df %>% 
  mutate(dist1 = pmap_dbl(list(lon, lat),     #pmap_dbl ensures output is vector of numbers
                          ~distGeo(c(-64.343043, 45.897932), 
                                   c(.x, .y)) / 1000))

Вам нужно будет изменить это, чтобы включить год и другие переменные, которыеЯ проигнорировал.

Проблема с вашим кодом заключалась в использовании термина df[...] внутри конвейера dplyr, который начинался с df.Лучше всего работать только с именами переменных, как указано выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...