R:插入数据框行对的中间值

R: Inserting Mid Values of Data Frame Row Pairs

我有一系列来自 Strava 的坐标,每 2.5 分钟记录一次,然后将它们添加到 QGIS 地图中。我想通过取每对经纬度的平均值来插入中间的点。

我知道我可以使用 for 循环,但我宁愿使用 apply 函数族之一。我知道我需要获取当前行,然后是除最后一行以外的所有行的下一行。

gpsSmall 是一个 data.frame 看起来像这样

activity_no lat     lon
----------- ---     ---
1           52.5111 -1.85222
1           52.5111 -1.86224
1           52.5111 -1.87226
... etc
2           52.6189 -1.85332
2           52.6284 -1.86332
2           52.6386 -1.87332
... etc

然后我编写了这些函数来创建额外的行,我将 rbind 到最后。

splitPoints <- function(point1, point2) {
    meanLatitude = (point1$lat + point2$lat)/2
    meanLongitude = (point1$lon + point2$lon)/2

    point1$lat = meanLatitude
    point1$lon = meanLongitude

    point1
}

newPoints <- sapply(seq_len(nrow(gpsSmall) - 1),
       function(i){
           splitPoints(gpsSmall[i,], gpsSmall[i+1,])
       })

但是,newPoints returns 矩阵 3(gpsSmall 中的列数)x 66(1 - gpsSmall 中的行数)。我做错了什么?

不使用应用函数,但像这样的东西可能会使它更容易一些。鉴于我认为您的问题是什么,应该这样做。我假设您希望 activity_no 成为一种分组机制。如果没有,那就更容易了。只需对整个数据集使用下面的 approx 函数,而不是先拆分它。

几个 tidyverse 包:

library(dplyr)
library(purrr)

加载您的数据片段:

dat <- tribble(
  ~activity_no, ~lat, ~lon,
  1,           52.5111, -1.85222,
  1,           52.5111, -1.86224,
  1,           52.5111, -1.87226,
  2,           52.6189, -1.85332,
  2,           52.6284, -1.86332,
  2,           52.6386, -1.87332
)

现在只需使用 ?approx 进行线性插值。将插值输出的长度设置为 n * 2 - 1 基本上表示在每次实际观察之间有 1 个新值。因为它是线性的,所以这将是平均值。如果需要,您可以调整输出并获得更高级别的插值。

dat %>%
  split(dat$activity_no) %>%
  map_dfr( ~ data.frame(activity_no = rep(.$activity_no[1], nrow(.) * 2 - 1),
                lat = approx(.$lat, n = nrow(.) * 2 - 1)$y,
                lon = approx(.$lon, n = nrow(.) * 2 - 1)$y))

   activity_no      lat      lon
1            1 52.51110 -1.85222
2            1 52.51110 -1.85723
3            1 52.51110 -1.86224
4            1 52.51110 -1.86725
5            1 52.51110 -1.87226
6            2 52.61890 -1.85332
7            2 52.62365 -1.85832
8            2 52.62840 -1.86332
9            2 52.63350 -1.86832
10           2 52.63860 -1.87332