Вычисление минимального расстояния между строкой и всеми предыдущими строками в R - PullRequest
0 голосов
/ 03 марта 2019

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

  grp    date    long lat rowid
1   1 1995-07-01   11  12     1
2   1 1995-07-05    3   0     2
3   1 1995-07-09   13   4     3
4   1 1995-07-13    4  25     4
5   2 1995-03-07   12   6     1
6   2 1995-03-10    3  27     2
7   2 1995-03-13   34   8     3
8   2 1995-03-16   25   9     4

Моя текущая попытка использует purrrlyr :: by_row, но метод слишком медленный.На практике каждая группа имеет тысячи дат и географических положений.Вот часть моей нынешней попытки:

calc_min_distance <- function(df, grp.name, row){
  df %>% 
    filter(
      group_name==grp.name
    ) %>% 
    filter(
      row_number() <= row
    ) %>% 
    mutate(
      last.lat = last(lat),
      last.long = last(long),
      rowid = 1:n()
    ) %>% 
    group_by(rowid) %>% 
    purrrlyr::by_row(
      ~haversinedistance.fnct(.$last.long, .$last.lat, .$long, .$lat),
      .collate='rows',
      .to = 'min.distance'
    ) %>% 
    filter(
      row_number() < n()
    ) %>% 
    summarise(
      min = min(min.distance)
    ) %>% 
    .$min
}

df_dist <-
  df %>% 
  group_by(grp_name) %>% 
  mutate(rowid = 1:n()) %>% 
  group_by(grp_name, rowid) %>% 
  purrrlyr::by_row(
    ~calc_min_distance(df, .$grp_name,.$rowid),
    .collate='rows',
    .to = 'min.distance'
  ) %>% 
  ungroup %>% 
  select(-rowid)

Предположим, что расстояние определяется как (лат + длинный) для справки ряд - (лат + длинный) для каждого парного ряда меньше, чем опорный ряд.Мой ожидаемый результат для grp 1 следующий:

  grp       date long lat rowid min.distance
1   1 1995-07-01   11  12     1            0
2   1 1995-07-05    3   0     2          -20
3   1 1995-07-09   13   4     3           -6
4   1 1995-07-13    4  25     4            6

Как быстро вычислить минимальное расстояние между текущим rowid и всеми rowid до него?

1 Ответ

0 голосов
/ 03 марта 2019

Вот как бы я поступил по этому поводу.В любом случае вам необходимо рассчитать все парные расстояния внутри группы, поэтому мы будем использовать geosphere::distm, который предназначен именно для этого.Я бы посоветовал пошагово пройтись по моей функции и посмотреть, что она делает, думаю, это будет иметь смысл.

library(geosphere)
find_min_dist_above = function(long, lat, fun = distHaversine) {
  d = distm(x = cbind(long, lat), fun = fun)
  d[lower.tri(d, diag = TRUE)] = NA
  d[1, 1] = 0
  return(apply(d, MAR = 2, min, na.rm = TRUE))
}

df %>% group_by(grp) %>%
  mutate(min.distance = find_min_dist_above(long, lat))
# # A tibble: 8 x 6
# # Groups:   grp [2]
#     grp date        long   lat rowid min.distance
#   <int> <fct>      <int> <int> <int>        <dbl>
# 1     1 1995-07-01    11    12     1           0 
# 2     1 1995-07-05     3     0     2     1601842.
# 3     1 1995-07-09    13     4     3      917395.
# 4     1 1995-07-13     4    25     4     1623922.
# 5     2 1995-03-07    12     6     1           0 
# 6     2 1995-03-10     3    27     2     2524759.
# 7     2 1995-03-13    34     8     3     2440596.
# 8     2 1995-03-16    25     9     4      997069.

Использование этих данных:

df = read.table(text = '  grp    date    long lat rowid
1   1 1995-07-01   11  12     1
2   1 1995-07-05    3   0     2
3   1 1995-07-09   13   4     3
4   1 1995-07-13    4  25     4
5   2 1995-03-07   12   6     1
6   2 1995-03-10    3  27     2
7   2 1995-03-13   34   8     3
8   2 1995-03-16   25   9     4', h = TRUE)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...