如何找到 R 中连续坐标之间的距离?
How can I find the distance between consecutive coordinates in R?
我有一个结构类似于下面创建的数据框:
id <- rep(c("a", "b", "c", "d"), each = 3)
date <- seq(as.Date("2019-01-30"), as.Date("2019-02-10"), by="days")
lon <- c(-87.1234, -86.54980, -86.234059, -87.2568, -87.65468, -86.54980, -86.234059, -86.16486, -87.156546, -86.234059, -86.16486, -87.156546)
lat <- c(26.458, 26.156, 25.468, 25.157, 24.154, 24.689, 25.575, 25.468, 25.157, 24.154, 26.789, 26.456)
data <- data.frame(id, date, lon, lat)
data <- data %>% arrange(id, date)
我想测量按 id 分组的 个连续 个点之间的距离。我不需要距离矩阵,这就是为什么我不使用 raster::pointDistance 的原因。我尝试将每个唯一的 id 分离到它自己的 sf 数据帧中(实际上我有 ~400 个 id,所以由于大小的原因,我不得不为实际计算分开)并使用以下代码:
#put rows for each id in their own dataframes
un1 <- unique(data$id)
for(i in seq_along(un1))
assign(paste0('id', i), subset(data, id == un1[i]))
#create point distance function
pt.dist <- function(dat){dat$pt.dist <- st_distance(dat, by_element=TRUE)
return(dat)}
#run function across every dataframe in working environment
e <- .GlobalEnv
nms <- ls(pattern = "id", envir = e)
for(nm in nms) e[[nm]] <- pt.dist(e[[nm]])
当我 运行 这样做时,我得到的只是一个几何列,其中 lon 和 lat 成对列出。我也试过 segclust2d::calc_distance 如下所示:
distance <- function(dat){calc_dist(dat, coord.names = c("lon", "lat"), smoothed = FALSE)}
for(nm in nms) e[[nm]] <- distance(e[[nm]])
其中returns一列距离均为0米
如有任何帮助,我们将不胜感激!
geosphere::dist*
支持这个。 most-accurate 是 distVincentyEllipsoid
(尽管对于较大的数据它可能会更慢),然后是 distVincentySphere
和 distHaversine
。它的 return 值以米为单位。
dplyr
library(dplyr)
data %>%
group_by(id) %>%
mutate(dist = c(NA, geosphere::distVincentyEllipsoid(cbind(lon, lat)))) %>%
ungroup()
# # A tibble: 12 x 5
# id date lon lat dist
# <chr> <date> <dbl> <dbl> <dbl>
# 1 a 2019-01-30 -87.1 26.5 NA
# 2 a 2019-01-31 -86.5 26.2 66334.
# 3 a 2019-02-01 -86.2 25.5 82534.
# 4 b 2019-02-02 -87.3 25.2 NA
# 5 b 2019-02-03 -87.7 24.2 118175.
# 6 b 2019-02-04 -86.5 24.7 126758.
# 7 c 2019-02-05 -86.2 25.6 NA
# 8 c 2019-02-06 -86.2 25.5 13744.
# 9 c 2019-02-07 -87.2 25.2 105632.
# 10 d 2019-02-08 -86.2 24.2 NA
# 11 d 2019-02-09 -86.2 26.8 291988.
# 12 d 2019-02-10 -87.2 26.5 105423.
基础 R
我们可以用 ave
得到同样的结果。因为它只迭代单个列,所以我们将 row-indices 作为要分组的第一个参数传递。因为它将 return 值强制为与第一个参数相同的 class
,所以我们将 row-indices 转换为 numeric
.
data$dist2 <- ave(
as.numeric(seq_len(nrow(data))), # values to use in calc
data$id, # grouping variable(s)
FUN = function(i) c(NA, geosphere::distVincentyEllipsoid(data[i, c("lon", "lat")]))
)
data
# id date lon lat dist2
# 1 a 2019-01-30 -87.12340 26.458 NA
# 2 a 2019-01-31 -86.54980 26.156 66334.13
# 3 a 2019-02-01 -86.23406 25.468 82534.47
# 4 b 2019-02-02 -87.25680 25.157 NA
# 5 b 2019-02-03 -87.65468 24.154 118175.40
# 6 b 2019-02-04 -86.54980 24.689 126757.93
# 7 c 2019-02-05 -86.23406 25.575 NA
# 8 c 2019-02-06 -86.16486 25.468 13743.74
# 9 c 2019-02-07 -87.15655 25.157 105631.82
# 10 d 2019-02-08 -86.23406 24.154 NA
# 11 d 2019-02-09 -86.16486 26.789 291988.42
# 12 d 2019-02-10 -87.15655 26.456 105422.87
在内部,对 FUN
函数的第二次调用为 "b"
id 组传递了 i=c(4,5,6)
。这些数字不需要连续;事实上,ave
优于其他 group-processing 函数的一个优点是它总是 return 与输入的顺序相同,因此将其值重新分配回原始帧是安全的.
我有一个结构类似于下面创建的数据框:
id <- rep(c("a", "b", "c", "d"), each = 3)
date <- seq(as.Date("2019-01-30"), as.Date("2019-02-10"), by="days")
lon <- c(-87.1234, -86.54980, -86.234059, -87.2568, -87.65468, -86.54980, -86.234059, -86.16486, -87.156546, -86.234059, -86.16486, -87.156546)
lat <- c(26.458, 26.156, 25.468, 25.157, 24.154, 24.689, 25.575, 25.468, 25.157, 24.154, 26.789, 26.456)
data <- data.frame(id, date, lon, lat)
data <- data %>% arrange(id, date)
我想测量按 id 分组的 个连续 个点之间的距离。我不需要距离矩阵,这就是为什么我不使用 raster::pointDistance 的原因。我尝试将每个唯一的 id 分离到它自己的 sf 数据帧中(实际上我有 ~400 个 id,所以由于大小的原因,我不得不为实际计算分开)并使用以下代码:
#put rows for each id in their own dataframes
un1 <- unique(data$id)
for(i in seq_along(un1))
assign(paste0('id', i), subset(data, id == un1[i]))
#create point distance function
pt.dist <- function(dat){dat$pt.dist <- st_distance(dat, by_element=TRUE)
return(dat)}
#run function across every dataframe in working environment
e <- .GlobalEnv
nms <- ls(pattern = "id", envir = e)
for(nm in nms) e[[nm]] <- pt.dist(e[[nm]])
当我 运行 这样做时,我得到的只是一个几何列,其中 lon 和 lat 成对列出。我也试过 segclust2d::calc_distance 如下所示:
distance <- function(dat){calc_dist(dat, coord.names = c("lon", "lat"), smoothed = FALSE)}
for(nm in nms) e[[nm]] <- distance(e[[nm]])
其中returns一列距离均为0米
如有任何帮助,我们将不胜感激!
geosphere::dist*
支持这个。 most-accurate 是 distVincentyEllipsoid
(尽管对于较大的数据它可能会更慢),然后是 distVincentySphere
和 distHaversine
。它的 return 值以米为单位。
dplyr
library(dplyr)
data %>%
group_by(id) %>%
mutate(dist = c(NA, geosphere::distVincentyEllipsoid(cbind(lon, lat)))) %>%
ungroup()
# # A tibble: 12 x 5
# id date lon lat dist
# <chr> <date> <dbl> <dbl> <dbl>
# 1 a 2019-01-30 -87.1 26.5 NA
# 2 a 2019-01-31 -86.5 26.2 66334.
# 3 a 2019-02-01 -86.2 25.5 82534.
# 4 b 2019-02-02 -87.3 25.2 NA
# 5 b 2019-02-03 -87.7 24.2 118175.
# 6 b 2019-02-04 -86.5 24.7 126758.
# 7 c 2019-02-05 -86.2 25.6 NA
# 8 c 2019-02-06 -86.2 25.5 13744.
# 9 c 2019-02-07 -87.2 25.2 105632.
# 10 d 2019-02-08 -86.2 24.2 NA
# 11 d 2019-02-09 -86.2 26.8 291988.
# 12 d 2019-02-10 -87.2 26.5 105423.
基础 R
我们可以用 ave
得到同样的结果。因为它只迭代单个列,所以我们将 row-indices 作为要分组的第一个参数传递。因为它将 return 值强制为与第一个参数相同的 class
,所以我们将 row-indices 转换为 numeric
.
data$dist2 <- ave(
as.numeric(seq_len(nrow(data))), # values to use in calc
data$id, # grouping variable(s)
FUN = function(i) c(NA, geosphere::distVincentyEllipsoid(data[i, c("lon", "lat")]))
)
data
# id date lon lat dist2
# 1 a 2019-01-30 -87.12340 26.458 NA
# 2 a 2019-01-31 -86.54980 26.156 66334.13
# 3 a 2019-02-01 -86.23406 25.468 82534.47
# 4 b 2019-02-02 -87.25680 25.157 NA
# 5 b 2019-02-03 -87.65468 24.154 118175.40
# 6 b 2019-02-04 -86.54980 24.689 126757.93
# 7 c 2019-02-05 -86.23406 25.575 NA
# 8 c 2019-02-06 -86.16486 25.468 13743.74
# 9 c 2019-02-07 -87.15655 25.157 105631.82
# 10 d 2019-02-08 -86.23406 24.154 NA
# 11 d 2019-02-09 -86.16486 26.789 291988.42
# 12 d 2019-02-10 -87.15655 26.456 105422.87
在内部,对 FUN
函数的第二次调用为 "b"
id 组传递了 i=c(4,5,6)
。这些数字不需要连续;事实上,ave
优于其他 group-processing 函数的一个优点是它总是 return 与输入的顺序相同,因此将其值重新分配回原始帧是安全的.