I have a spatial vector (Spatvector) with points arranged in groups. I want to calculate the distance of each point to the first point in the group.
Trans2024_df
Name Distance_to_first
1 T01 0
2 T01 1.2
3 T01 2.5
4 T02 0
5 T02 0.5
6 T02 1.2
7 T02 1.7
8 T03 0
9 T03 1.3
I managed to get the distance to the previous point.
VectorPoints_sf <- st_as_sf(VectorPoints)
VectorPoints_sf %>%
mutate(
distance_next = sf::st_distance(
geometry,
lead(geometry),
by_element = TRUE))
Name distance_next
1 T01 0
2 T01 1.2
3 T01 1.3
4 T02 5
5 T02 0.5
6 T02 0.7
7 T02 1.5
8 T03 2
9 T03 1.3
But I can't figure out how to get the distance to the first point. I assumed that it would work with dplr::first()
VectorPoints_sf %>%
group_by(Transect) %>%
mutate(
distance_first = sf::st_distance(
geometry,
first(geometry),
by_element = TRUE))
But I get the following error:
Error in `stopifnot()`:
ℹ In argument: `distance_first = sf::st_distance(geometry, geometry[1], by_element = TRUE)`.
ℹ In group 1: `Transect = "T09"`.
Caused by error in `sf::st_distance()`:
! length(x) == length(y) is not TRUE
I have a spatial vector (Spatvector) with points arranged in groups. I want to calculate the distance of each point to the first point in the group.
Trans2024_df
Name Distance_to_first
1 T01 0
2 T01 1.2
3 T01 2.5
4 T02 0
5 T02 0.5
6 T02 1.2
7 T02 1.7
8 T03 0
9 T03 1.3
I managed to get the distance to the previous point.
VectorPoints_sf <- st_as_sf(VectorPoints)
VectorPoints_sf %>%
mutate(
distance_next = sf::st_distance(
geometry,
lead(geometry),
by_element = TRUE))
Name distance_next
1 T01 0
2 T01 1.2
3 T01 1.3
4 T02 5
5 T02 0.5
6 T02 0.7
7 T02 1.5
8 T03 2
9 T03 1.3
But I can't figure out how to get the distance to the first point. I assumed that it would work with dplr::first()
VectorPoints_sf %>%
group_by(Transect) %>%
mutate(
distance_first = sf::st_distance(
geometry,
first(geometry),
by_element = TRUE))
But I get the following error:
Error in `stopifnot()`:
ℹ In argument: `distance_first = sf::st_distance(geometry, geometry[1], by_element = TRUE)`.
ℹ In group 1: `Transect = "T09"`.
Caused by error in `sf::st_distance()`:
! length(x) == length(y) is not TRUE
Share
Improve this question
asked Mar 6 at 16:53
macemace
5081 gold badge7 silver badges24 bronze badges
2
|
1 Answer
Reset to default 0Example data
library(terra)
set.seed(1)
v <- vect(matrix(runif(40), ncol=2), crs="local")
v$Name <- rep(LETTERS[1:5], each=4)
Computing the distances can be done like this
x <- lapply(split(v, "Name"), \(x) distance(x[-1], x[1]))
Or like this to create the output data.frame you want, and checking for the degenerate case where there is only a single point
x <- lapply(split(v, "Name"), \(x) {
if (nrow(x) == 1) {
dist <- NA
} else {
dist <- distance(x[-1], x[1])
}
data.frame(Name=x[1]$Name, dist=dist)
})
do.call(rbind, x)
# Name dist
#1 A 0.7303860
#2 A 0.4178128
#3 A 1.0333374
#4 B 0.7067796
#5 B 0.7851554
#6 B 0.4733401
#7 C 0.7759276
#8 C 0.5738372
#9 C 0.5270442
#10 D 0.4315181
#11 D 0.3439516
#12 D 0.2577641
#13 E 0.7390779
#14 E 0.3448722
#15 E 0.3876103
If you wanted the sequential distance by group instead, and the data are sorted by group, you could do
dst <- data.frame(Name=v$Name, d=distance(v, sequential=TRUE))
i <- which(v$Name[-1] != v$Name[-nrow(v)]) + 1
dst$d[i] <- 0
by_element = TRUE
. – margusl Commented Mar 6 at 17:30