【问题标题】:Calculating average speed from lon/lat and timestamp using distance (geosphere) and difftime使用距离(地球圈)和 difftime 从 lon/lat 和时间戳计算平均速度
【发布时间】:2017-06-07 12:48:19
【问题描述】:

我正在尝试使用 geosphere 中的 distm 函数计算两个连续实例(行)之间的半正弦距离。最终,我想使用以米为单位的距离除以以秒为单位的时间差来计算平均速度。

这就是我以秒为单位计算时差的方式

df$Timediff_secs <- 
  with(df, 
       difftime(Timestamp, ave(Timestamp, ID, FUN=lag), units='secs'))

之前有人问过similar question,答案确实有效,但我需要按 ID 进行索引,以便每个新 ID 都以 NA 开头。我想创建一个名为df$Distance 的新列。

需要对其进行编辑,使其按 ID 进行索引,并且第一行为 NA(因为要计算的距离没有差异)

library(geosphere)
metersPerMile <- 1609.34
pts <- df1[c("lon", "lat")]

## Pass in two derived data.frames that are lagged by one point
segDists <- distVincentyEllipsoid(p1 = pts[-nrow(df),], 
                                  p2 = pts[-1,])
sum(segDists)/metersPerMile
# [1] 1013.919

这是我从链接中复制的一些示例数据

> df
          Timestamp      ID      lat       lon
2012-11-12 02:08:41      1  76.57169 -110.8070
2012-11-12 02:09:41      1  76.44325 -110.7525
2012-11-12 02:10:41      1  76.90897 -110.8613
2012-11-12 03:18:41      2  76.11152 -110.2037
2012-11-12 03:19:41      2  76.29013 -110.3838
2012-11-12 03:20:41      2  76.15544 -110.4506

感觉我已经尝试了一切,非常感谢任何帮助!

【问题讨论】:

    标签: r timestamp rows geospatial distance


    【解决方案1】:

    dplyr::lagdata.table::shift 和分组对此很方便,尽管它可以在 base 中手动完成,例如 c(NA, variable[-length(variable)])aggregate

    library(dplyr)
    
    df <- structure(list(Timestamp = structure(c(1352704121, 1352704181, 1352704241, 1352708321, 1352708381, 1352708441), 
                                               class = c("POSIXct", "POSIXt"), tzone = ""), 
                         ID = c(1L, 1L, 1L, 2L, 2L, 2L), 
                         lat = c(76.57169, 76.44325, 76.90897, 76.11152, 76.29013, 76.15544), 
                         lon = c(-110.807, -110.7525, -110.8613, -110.2037, -110.3838, -110.4506)), 
                    class = "data.frame", .Names = c("Timestamp", "ID", "lat", "lon"), row.names = c(NA, -6L))
    
    df <- df %>% 
        group_by(ID) %>%
        mutate(dist_m = geosphere::distVincentyEllipsoid(cbind(lon, lat), 
                                                         cbind(lag(lon), lag(lat))), 
               time_s = difftime(Timestamp, lag(Timestamp), units = 'secs'), 
               speed_m_per_s = dist_m / as.integer(time_s))
    
    df
    #> # A tibble: 6 x 7
    #> # Groups:   ID [2]
    #>             Timestamp    ID      lat       lon   dist_m  time_s speed_m_per_s
    #>                <dttm> <int>    <dbl>     <dbl>    <dbl>  <time>         <dbl>
    #> 1 2012-11-12 02:08:41     1 76.57169 -110.8070       NA NA secs            NA
    #> 2 2012-11-12 02:09:41     1 76.44325 -110.7525 14408.23 60 secs      240.1371
    #> 3 2012-11-12 02:10:41     1 76.90897 -110.8613 52065.53 60 secs      867.7588
    #> 4 2012-11-12 03:18:41     2 76.11152 -110.2037       NA NA secs            NA
    #> 5 2012-11-12 03:19:41     2 76.29013 -110.3838 20507.15 60 secs      341.7859
    #> 6 2012-11-12 03:20:41     2 76.15544 -110.4506 15140.03 60 secs      252.3338
    

    由于data.frame已经分组,聚合只需要求和:

    df_avg <- df %>% 
        summarise(dist_m = sum(dist_m, na.rm = TRUE), 
                  time_s = sum(as.integer(time_s), na.rm = TRUE), 
                  speed_m_per_s = dist_m / time_s)
    
    df_avg
    #> # A tibble: 2 x 4
    #>      ID   dist_m time_s speed_m_per_s
    #>   <int>    <dbl>  <int>         <dbl>
    #> 1     1 66473.76    120      553.9480
    #> 2     2 35647.18    120      297.0598
    

    单位是米每秒;随意转换。

    【讨论】:

    • 就像一个魅力,除了 ID = 2 的第一个值不以 NA 开头,现在它是 90653.24,因为它只是继续,它应该从每个 ID 的第一个实例重新开始计算。非常感谢您的帮助@alistaire
    • 我刚刚弄清楚了分组部分,但 stackoverflow 不允许我发表评论,对此感到抱歉。再次感谢您的帮助!
    • 希望我没有在这里推运气@alistaire@amatsuo_net ;) 但我想知道你是否可以帮助我解决一个试图索引二进制特征的小问题。索引仅适用于列中的第一个 1 或 0,但我需要该函数在每次行值更改为 1 或 0 时进行索引。我已经解决了一个类似的问题,即在一周中的几天进行索引时,将它们设为数字,因为每一天每月只发生一次,而不是说“星期一”,它发生了 4 次。明白我的意思了吗?这个问题有简单的解决方案吗?再次感谢您的帮助!
    • 听起来像rle(“运行长度编码”)或data.table::rleid。如果您搜索,这里有很多关于它的问题,但如果您找不到类似的问题,请提出一个新问题。
    • 感谢您的回复,我已经尝试过 rle 但我不确定我是否正确地合并了它。例如,如果我们查看您上面发布的代码,如果按功能分组“ ID”是一个二进制特征,我将如何在精确的平均速度函数中使用 rle.. 谢谢
    【解决方案2】:

    如果您倾向于使用data.table,方法如下:

    df[, Timestamp := parse_datetime(Timestamp)]
    df[, distance := distVincentyEllipsoid(p1 = cbind(lon, lat), 
                                           p2 = cbind(shift(lon), shift(lat))), 
       by = ID]
    output <- df[, .(time_diff = as.numeric(Timestamp[.N] - Timestamp[1], unit = "secs") ,
                     tot_distance = sum(distance, na.rm = TRUE)), by = ID]
    output[, avg_speed := tot_distance /time_diff]
    ##    ID time_diff tot_distance avg_speed
    ## 1:  1       120     66473.26  553.9438
    ## 2:  2       120     35646.55  297.0546
    

    【讨论】:

      猜你喜欢
      • 2012-04-04
      • 2022-08-23
      • 1970-01-01
      • 1970-01-01
      • 2013-01-26
      • 2016-08-05
      • 2019-02-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多