Как я могу рассчитать расстояние между широтой и долготой по рядам столбцов в R?

Мой df выглядит так:

    bid        ts    latitude  longitude
1  827566 1999-10-07 42.40944 -88.17822
2  827566 2013-04-11 41.84740 -87.63126
3 1902966 2012-05-02 45.52607 -94.20649
4 1902966 2013-03-25 41.94083 -87.65852
5 3211972 2012-08-14 43.04786 -87.96618
6 3211972 2013-08-02 41.88258 -87.63760

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

library(geosphere)
   lengthdata <- nrow(twopoint)
   twopointdata <- data.frame(matrix(ncol = 4, nrow =lengthdata))
   x <- c("bid", "time", "d", "dsq")
   colnames(twopointdata) <- x
   n <- numeric()
   n <- 1

   for (i in 1:lengthdata)
   {
     if (twopoint[i+1,1] == twopoint[i,1]) 
     {
       twopointdata[n,1] <- twopoint[i+1,1]
       twopointdata[n,2] <- as.numeric(twopoint[i+1,5]-twopoint[i,5])
       twopointdata[n,3] <- distm(c(twopoint[i+1,10], twopoint[i+1,9]), 
                              c(twopoint[i,10],twopoint[i,9]), fun = 
                                   distHaversine)
       twopointdata[n,4] <- twopoint[n,3]^2
       n <- n+1
     }

   }
   attach(twopointdata)
   head(twopointdata)

(некоторые номера столбцов отключены, потому что я убрал несколько строк, чтобы отобразить их более четко)

Мой результат выглядит так:

      bid time    d          dsq
1  827566 4935  77159.8 5.677201e+11
2 1902966  327 660457.0 6.436004e+16
3 3211972  353 132494.8 3.540118e+12
4 3692174 4722 727359.6 6.394166e+16
5 4404655 4833 201644.7 1.092944e+13
6 6644203 4518 210485.9 6.721980e+16

Он имеет идентификаторы для каждой точки данных, разницу во времени между ними, расстояние, рассчитанное по долготе и широте, и квадрат расстояния. ПРОБЛЕМА: это очень медленно, и в конечном итоге я буду делать это с очень большим набором данных.

Я смог сделать это без цикла for с разницей во времени, используя dplyr следующим образом:

 library(dplyr)
 library(geosphere)
 latlongdata2 <- latlongdata 
 latlongdata2 %>%
  group_by(bid)%>%
  transmute(
    bid = bid,
    t = c(NA,diff(ts)))

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

P.S. Общая цель проекта - провести анализ данных по среднеквадратическому смещению.


person nateswill    schedule 04.11.2017    source источник


Ответы (1)


Я думаю, вы немного усложняете. Я бы хотел, чтобы у geosphere::distHaversine был чуть более интуитивно понятный метод вызова (похожий, скажем, на diff), но обойти его несложно:

dat <- read.table(text = "  bid        ts    latitude  longitude
 827566 1999-10-07 42.40944 -88.17822
 827566 2013-04-11 41.84740 -87.63126
1902966 2012-05-02 45.52607 -94.20649
1902966 2013-03-25 41.94083 -87.65852
3211972 2012-08-14 43.04786 -87.96618
3211972 2013-08-02 41.88258 -87.63760", header = TRUE, stringsAsFactors = FALSE)
dat$ts <- as.Date(dat$ts)

library(dplyr)
library(geosphere)
group_by(dat, bid) %>%
  mutate(
    d = c(NA,
          distHaversine(cbind(longitude[-n()], latitude[-n()]),
                        cbind(longitude[  -1], latitude[  -1]))),
    dts = c(NA, diff(ts))
  ) %>%
  ungroup() %>%
  filter( ! is.na(d) )
# # A tibble: 3 × 6
#       bid         ts latitude longitude         d   dts
#     <int>     <date>    <dbl>     <dbl>     <dbl> <dbl>
# 1  827566 2013-04-11 41.84740 -87.63126  77159.35  4935
# 2 1902966 2013-03-25 41.94083 -87.65852 660457.41   327
# 3 3211972 2013-08-02 41.88258 -87.63760 132494.65   353
person r2evans    schedule 04.11.2017
comment
Обновление: distHaversine предполагает сферическую планету, может быть более подходящим (менее предвзятым) использовать удобные для эллипсоидов вычисления, такие как geosphere::distGeo. Дополнительная информация о моделях и их относительной точности подробно обсуждается в geosphere вводная виньетка (также есть ссылка на _4 _ ). - person r2evans; 31.07.2018