knitr::opts_chunk$set(echo = TRUE)
In this vignette you will learn the differences between three distance coefficients available for assessing trajectory resemblance. We use small datasets where trajectories occur in a space of two dimensions, so that geometric calculations can be followed more easily.
First of all, we load ecotraj
:
library(ecotraj)
Let $T_1$ and $T_2$ be two trajectories to be compared. The first distance metric is Segment Path Distance (SPD) (Besse et al. 2016), defined as the average of the distances between each point composing $T_1$ and $T_2$:
[D_{SP}(T_1, T_2) = \frac{1}{n}\sum_{i=1}^{n}{D_{pt}(x_{1i}, T_2)}]
where $D_{pt}$ is the distance between a point a a trajectory. SPD is not symmetric so it needs to be symmetrized:
[D_{SSP}(T_1, T_2) = \frac{D_{SP}(T_1, T_2) + D_{SP}(T_2, T_1)}{2}]
SPD is appropriate to compare the location and shape of trajectories, but is not sensitive to trajectory direction. For this reason, De Cáceres et al. (2019) introduced the Directed Segment Path Dissimilarity (DSPD), defined as the average of the distance between each directed segment of $T_1$ and $T_2$:
[D_{DSP}(T_1, T_2) = \frac{1}{n-1}\sum_{i=1}^{n-1}{D_{DS}(S_{1i}, T_2)}]
where $D_{SP}$ is the distance between a segment and a trajectory. As before, DSPD is not symmetric so it needs to be symmetrized:
[D_{SDSP}(T_1, T_2) = \frac{D_{DSP}(T_1, T_2) + D_{DSP}(T_2, T_1)}{2}]
DSPD is an appropriate metric to compare the location, shape and direction of trajectories. Nevertheless, the metric does not allow taking into account differences in trajectory speed, because it does not use the information regarding the time of observations (only the survey order).
If $T_1$ and $T_2$ represent the dynamics of two sites that have been surveyed synchronously (i.e., if $n = m$ and $t_{11} = t_{21}$; $t_{12}=t_{22}$;... ; $t_{1n} = t_{2n}$), a straightforward way of comparing them is to calculate the average across surveys of dissimilarity between the two sites, i.e. the mean of the sequence ${d(x_{11}, x_{21}), \, d(x_{12}, x_{22}), \, \dots,\, d(x_{1n}, x_{2n})}$. For a more general solution the Time-Sensitive Path Distance (TSPD) is the average of distances between each observation in $T_1$ and $T_2$:
[D_{TSP}(T_1, T_2) = \frac{1}{n}\sum_{i=1}^{n}{D_{ot}({x_{1i}, t_{1i}}, T_2)}]
where $D_{ot}$ is the distance between an observation and a trajectory. $D_{ot}$ is the calculated as the distance between $x_{1i}$ and the point in $T_2$ corresponding to time $t_{1i}$, which may need to be interpolated if does not correspond to any value in ${t_{21}, t_{22}, \dots,t_{2m}}$. If $t_{1i}$ is beyond the time boundaries of $T_2$, then the distance to the closest time point is taken. As before, TSPD is not symmetric so it needs to be symmetrized:
[D_{STSP}(T_1, T_2) = \frac{D_{TSP}(T_1, T_2) + D_{TSP}(T_2, T_1)}{2}]
TSPD is sensitive to differences in location, shape, direction and speed, as will be illustrated in the following examples.
Let us first compare the behavior of the three distance metrics for comparisons between linear trajectories. In all cases, the reference trajectory is composed of three linear segments.
We compare first a linear trajectory with its oposed one, i.e. a trajectory going in the exact oposite sense.
sites <- c("1","1","1","1","2","2","2", "2") times <- c(0,1,2,3,0,1,2,3) xy<-matrix(0, nrow=8, ncol=2) xy[2,2]<-1 xy[3,2]<-2 xy[4,2]<-3 xy[5,2]<-3 xy[6,2]<-2 xy[7,2]<-1 xy[8,2]<-0 x <- defineTrajectories(dist(xy), sites = sites, times = times)
We can display the two (overlapping) trajectories using:
trajectoryPCoA(x, traj.colors = c("black", "red", "blue"), lwd = 2, time.labels = TRUE)
The two trajectories have the same lengths and speeds:
trajectoryLengths(x) trajectorySpeeds(x)
When we examine trajectory (temporal) shifts we see the oposing character:
trajectoryShifts(x)
Calculating SPD yields zero dissimilarity, because the distance does not take into account differences in direction:
trajectoryDistances(x, distance.type = "SPD")
The other two dissimilarity metrics do yield non-zero values:
trajectoryDistances(x, distance.type = "DSPD") trajectoryDistances(x, distance.type = "TSPD")
Here we compare three trajectories with the same linear pathway and speed. They only differ in the number of segments used to describe them:
sites <- c("1","1","1","1","2","2","2","3","3") times <- c(0,1,2,3,0,1.5,3,0,3) xy<-matrix(0, nrow=9, ncol=2) xy[2,2]<-1 xy[3,2]<-2 xy[4,2]<-3 xy[6,2]<-1.5 xy[7,2]<-3 xy[9,2]<-3 x <- defineTrajectories(dist(xy), sites = sites, times = times)
We plot the three trajectories in separate panels for clarity:
par(mfrow=c(3,1)) trajectoryPCoA(subsetTrajectories(x,"1"), traj.colors = c("black"), lwd = 2, time.labels = TRUE) trajectoryPCoA(subsetTrajectories(x,"2"), traj.colors = c("red"), lwd = 2, time.labels = TRUE) trajectoryPCoA(subsetTrajectories(x,"3"), traj.colors = c("blue"), lwd = 2, time.labels = TRUE)
Note that reversals may occur because of PCoA eigen analysis. But together the trajectories look like:
trajectoryPCoA(x, traj.colors = c("black", "red", "blue"), lwd = 2, time.labels = TRUE)
We can check that the three trajectories have the same total length and average speed:
trajectoryLengths(x)
trajectorySpeeds(x)
There are no temporal shifts between the trajectories:
trajectoryShifts(x)
Here SPD yields zero distance, because the three trajectories have the same shape:
trajectoryDistances(x, distance.type = "SPD")
Since it is defined by means of distances between directed segments, DSPD seems to be affected by the different segmentation of trajectories, so that it yields non-zero values:
trajectoryDistances(x, distance.type = "DSPD")
In contrast, TSPD yields again zero distance values, because the trajectories do not differ in neither speed or shape.
trajectoryDistances(x, distance.type = "TSPD")
In this example the three trajectories have the same segments and pathways, but they differ in the speed of changes:
sites <- c("1","1","1","1","2","2","2","2","3","3","3","3") times <- c(0,0.5,1,1.5,0,1,2,3,0,2,4,6) xy<-matrix(0, nrow=12, ncol=2) xy[2,2]<-1 xy[3,2]<-2 xy[4,2]<-3 xy[5:8,2] <- xy[1:4,2] xy[9:12,2] <- xy[1:4,2] x <- defineTrajectories(dist(xy), sites = sites, times = times)
Again we use separate plots to show the differences in speed:
par(mfrow=c(3,1)) trajectoryPCoA(subsetTrajectories(x,"1"), traj.colors = c("black"), lwd = 2, time.labels = TRUE) trajectoryPCoA(subsetTrajectories(x,"2"), traj.colors = c("red"), lwd = 2, time.labels = TRUE) trajectoryPCoA(subsetTrajectories(x,"3"), traj.colors = c("blue"), lwd = 2, time.labels = TRUE)
We can check that there are no differences in segment or total path lengths, but they indeed differ in trajectory speed:
trajectoryLengths(x) trajectorySpeeds(x)
Differences in speed also lead to temporal shifts between trajectories:
trajectoryShifts(x)
If we calculate distances using SPD, the distance metric does not detect the differences in speed and tells us that the trajectories are equal:
trajectoryDistances(x, distance.type = "SPD")
And the same happens with DSPD:
trajectoryDistances(x, distance.type = "DSPD")
It is only when we apply TSPD that we can observe differences between trajectories:
trajectoryDistances(x, distance.type = "TSPD")
The distance between the first and the third trajectory is largest because their difference in speed is also largest.
Let us now evaluate a case where trajectories are the same but have been displaced in one dimension:
sites <- c("1","1","1","1","2","2","2","2","3","3","3","3") times <- c(1,2,3,4,1,2,3,4,1,2,3,4) xy<-matrix(0, nrow=12, ncol=2) xy[2,2]<-1 xy[3,2]<-2 xy[4,2]<-3 # States are all shifted half unit with respect to site "1" xy[5:8,2] <- xy[1:4,2] + 0.5 # States are all shifted one unit with respect to site "1" xy[9:12,2] <- xy[1:4,2] + 1.0 x <- defineTrajectories(dist(xy), sites = sites, times = times)
We use a single plot, though not very clear, to display the three trajectories:
trajectoryPCoA(x, traj.colors = c("black", "red", "blue"), lwd = 2, time.labels = TRUE)
In this case differences do not exist in terms of lengths nor speeds:
trajectoryLengths(x) trajectorySpeeds(x)
But (temporal) shifts reflect the spatial ones:
trajectoryShifts(x)
In this case, all three metrics are responsive to differences in trajectory location:
trajectoryDistances(x, distance.type = "SPD") trajectoryDistances(x, distance.type = "DSPD") trajectoryDistances(x, distance.type = "TSPD")
In this example, the three linear trajectories are surveyed the same times but they differ in total path length due to differences in trajectory speed.
sites <- c("1","1","1","1","2","2","2","2","3","3","3","3") times <- c(0,1,2,3,0,1,2,3,0,1,2,3) xy<-matrix(0, nrow=12, ncol=2) xy[2,2]<-1 xy[3,2]<-2 xy[4,2]<-3 xy[5:8,2] <- xy[1:4,2]*1.5 xy[9:12,2] <- xy[1:4,2]*2 x <- defineTrajectories(dist(xy), sites = sites, times = times)
We draw the three (overlapping) trajectories:
trajectoryPCoA(x, traj.colors = c("black", "red", "blue"), lwd = 2, time.labels = TRUE)
In this case both lengths and speeds are different between trajectories:
trajectoryLengths(x) trajectorySpeeds(x)
This is also translated to trajectory shifts:
trajectoryShifts(x)
Since the trajectories differ in length, this is captured by all three metrics:
trajectoryDistances(x, distance.type = "SPD") trajectoryDistances(x, distance.type = "DSPD") trajectoryDistances(x, distance.type = "TSPD")
In this second set of examples we examine the behavior of the metrics when comparing trajectories that are not always linear.
Here the three trajectories have the same length and speed, but trajectory 2 and 3 are progressively curved:
sites <- c("1","1","1","1","2","2","2","2","3","3","3","3") surveys <- c(1,2,3,4,1,2,3,4,1,2,3,4) xy<-matrix(0, nrow=12, ncol=2) xy[2,2]<-1 xy[3,2]<-2 xy[4,2]<-3 xy[5:6,2] <- xy[1:2,2] xy[7,1]<-0+sqrt(0.5) xy[7,2]<-1+sqrt(0.5) xy[8,2]<-xy[7,2] xy[8,1]<-xy[7,1]+1 xy[9:10,2] <- xy[1:2,2] xy[11,1] <- 1.0 xy[11,2] <- 1.0 xy[12,1] <- 1.0 xy[12,2] <- 0.0 x <- defineTrajectories(dist(xy), sites = sites, times = times)
trajectoryPCoA(x, traj.colors = c("black", "red", "blue"), lwd = 2, time.labels = TRUE)
As expected, no differences are found in terms of lengths or speeds:
trajectoryLengths(x) trajectorySpeeds(x)
The three distance metrics are responsive to differences of trajectory shape:
trajectoryDistances(x, distance.type = "SPD") trajectoryDistances(x, distance.type = "DSPD") trajectoryDistances(x, distance.type = "TSPD")
This example is similar to the previous one, but here we changed the survey times, so that the observed trajectory shapes correspond also to different speeds:
sites <- c("1","1","1","1","2","2","2","2","3","3","3","3") times <- c(0,0.5,1,1.5,0,1,2,3,0,2,4,6) xy<-matrix(0, nrow=12, ncol=2) xy[2,2]<-1 xy[3,2]<-2 xy[4,2]<-3 xy[5:6,2] <- xy[1:2,2] xy[7,1]<-0+sqrt(0.5) xy[7,2]<-1+sqrt(0.5) xy[8,2]<-xy[7,2] xy[8,1]<-xy[7,1]+1 xy[9:10,2] <- xy[1:2,2] xy[11,1] <- 1.0 xy[11,2] <- 1.0 xy[12,1] <- 1.0 xy[12,2] <- 0.0 x <- defineTrajectories(dist(xy), sites = sites, times = times)
The trajectory plot looks as before, except for the time labels:
trajectoryPCoA(x, traj.colors = c("black", "red", "blue"), lwd = 2, time.labels = TRUE)
In this case trajectories differ in speed but not length:
trajectoryLengths(x) trajectorySpeeds(x)
The three metrics detect differences in shape, as before.
trajectoryDistances(x, distance.type = "SPD") trajectoryDistances(x, distance.type = "DSPD") trajectoryDistances(x, distance.type = "TSPD")
However, note that the values of SPD and DSPD are exactly the same to those of the previous example, whereas TSPD yields higher distance values because of the differences in trajectory speed.
Besse, P., Guillouet, B., Loubes, J.-M. & François, R. (2016). Review and perspective for distance based trajectory clustering. IEEE Trans. Intell. Transp. Syst., 17, 3306–3317.
De Cáceres M, Coll L, Legendre P, Allen RB, Wiser SK, Fortin MJ, Condit R & Hubbell S. (2019). Trajectory analysis in community ecology. Ecological Monographs 89, e01350.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.