Code to calculate average distance traveled each day and other spatial/ telemetry analyses

Hi everyone,

Here is a sample of my data which features ID (3 periods), date/time, and longitude and latitude co-ordinates.

dput(head(turtles, 20))
structure(list(id = c("Pre", "Pre", "Pre", "Pre", "Pre", "Pre",
"Pre", "Pre", "Pre", "Pre", "Pre", "Pre", "Pre", "Pre", "Pre",
"Pre", "Pre", "Pre", "Pre", "Pre"), date = c("2020-02-03", "2020-02-03",
"2020-02-03", "2020-02-03", "2020-02-03", "2020-02-03", "2020-02-03",
"2020-02-03", "2020-02-03", "2020-02-03", "2020-02-03", "2020-02-03",
"2020-02-03", "2020-02-03", "2020-02-03", "2020-02-03", "2020-02-03",
"2020-02-03", "2020-02-03", "2020-02-03"), time = c("8:30:00 AM",
"8:35:00 AM", "8:40:00 AM", "8:45:00 AM", "8:50:00 AM", "8:55:00 AM",
"9:00:00 AM", "9:05:00 AM", "9:10:00 AM", "9:15:00 AM", "9:20:00 AM",
"9:25:00 AM", "9:30:00 AM", "9:35:00 AM", "9:40:00 AM", "9:45:00 AM",
"9:50:00 AM", "9:55:00 AM", "10:00:00 AM", "10:05:00 AM"), x = c(-34.035352,
-34.035352, -34.035352, -34.035388, -34.035388, -34.035388, -34.036117,
-34.036117, -34.036117, -34.036117, -34.036117, -34.036117, -34.038561,
-34.038561, -34.038561, -34.038561, -34.037691, -34.038561, -34.038562,
-34.038562), y = c(23.273798, 23.273798, 23.273798, 23.274721,
23.274721, 23.274721, 23.274818, 23.274818, 23.274818, 23.274818,
23.274818, 23.274818, 23.273766, 23.273766, 23.273766, 23.273766,
23.273787, 23.273766, 23.272833, 23.272833)), row.names = c(NA,
20L), class = "data.frame")

I would like advise on how to alter this code to reflect the mean distance traveled each day (and shown as the mean for every date available so I have enough to conduct further analyses), and not the mean distance p/d overall for each of the 3 periods (ID). As it stands I am only getting one mean number per ID. Below is the code I have used so far:

total.path.df <- data.frame(turtles.ltraj[[1]], id = attr(turtles.ltraj[[1]], "id"))

for(i in 2:length(turtles.ltraj)) {
total.path.df <- rbind(total.path.df,
data.frame(turtles.ltraj[[i]], id = attr(turtles.ltraj[[i]], "id")))

total.path.df$distperday <- total.path.df$dist / (total.path.df$dt/60/60/24)


path.summary <- aggregate(distperday~id, data = total.path.df, FUN = mean)
path.summary$sd <- aggregate(distperday~id, data = total.path.df, FUN = sd)$distperday

Also, if anyone could please advise on further analyses? I will do an LME to compare differences between the 3 periods, but I would love to measure differences in speed of movement and clustering if possible. I have tried numerous packages (e.g. ctmm, movehmm etc) and numerous codes (too many to show here) and can never seem to get what I want, but I'm sure there is a simple way. I have some visualisations already, it is mainly the stats which I can then put into a model that I am after.

Many thanks in advance!

Hi Pman
Thank you for the sample data.

There is a couple of problems though, one with the sample data and one with the code.

The sample data one is dput(head(turtles, 20)) is only giving us one of the three ID values. Not a serious problem and one we should easily get around.

The code problem looks a bit more dicy. There is no reference to the turtles data.frame anywhere is your code. It looks like your data is stored in a list turtles.ltraj and you are pulling out various elements to produce a data.frame **total.path.df ** but we have no idea what that is.

Could you step back a bit and describe your research question and data at the study level?

Something along the lines of, "I am tracking junior painted turtles in the wilds of Patagonia and I measuring how fast or far they go in a day. And then describe what measures you have"?

It looks like *turtles is being drawn from turtles.ltraj[[1]] but why are you using id = attr(turtles.ltraj[[1]], "id"). I would not have thought you would need it with an existing data.frame.

I clearly do not understand the structure of your data.

Hi jrkrideau,

Thanks so much for your reply!

Yes of course, I am looking at differences in the movement patterns of elephants during three different periods - pre-lockdown, during-lockdown, and post-lockdown. Each day has an entry every 5 minutes of the overall position of the herd based on position on a grid map, which was then converted into longitude and latitude coordinates. I would like to see if there are differences in how much they moved, how quickly they moved, and to identify any patterns/ clusters/ differences between these periods. The turtles name is due to the tutorial I've been following online.

This is the beginning code from data frame to .ltraj object:
turtles.ltraj <- as.ltraj(xy = turtles[,c("x", "y")],
date = as.POSIXct(paste(turtles$Date, turtles$Time, sep = " ")),
id = turtles$Lock)

I basically have 4 factors: ID (lockdown phase), latitude co-ords, longitude co-ords, and date/time. The reason for id = attr(turtles...) was to create a data frame to hold the contents of bltu.paths with a column for id, and is based on the instructions I've been following online. This area is fairly new to me so I've tried my best to learn from websites/ tutorials but clearly have gotten quite stuck.

Thanks so much for your help I appreciate it so much!

Ah, thanks. I am disappointed that we have no painted turtles but I'm bearing up.

I have never worked with this kind of spatial data so I may not be of much help but can you point me to the tutorial that you are following. It may give me or other readers some idea of what is going on.

R supports a number of special interest mailing groups Special interest mailing groups and the R-SIG_Ecology and the R-SIG-Geo lists might be a good place to ask questions or at least look around.


Thank you so much for your reply and so sorry for the delay getting back to you!

Okay not to worry, thanks so much anyway. The link to the tutorial is here:

Okay will try on the specialist groups too. Thanks so much for taking the time to help me, I really appreciate it :smiley:

It's hard to tell but it looks like your problem is that date = as.POSIXct(paste(turtles$date, turtles$time, sep = " ") was not working.

Your sample data only has id = pre values so I cannot check out the entire code but I can get a plot if I comment out the for loop.

I think this will work.


dat1  <- read.csv("elephants.csv")
dat1$ldate  <- ymd_hms(paste(dat1$date,dat1$time))  #use lubridate to get date-time variable
dat1  <- dat1[ , c("id", "x", "y", "ldate")]

dat1.ltraj <- as.ltraj(xy = dat1[,c("x", "y")], 
                       date = dat1$ldate, 
                       id = dat1$id)

total.path.df <- data.frame(dat1.ltraj[[1]], id = attr(dat1.ltraj[[1]], "id"))

 for(i in 2:length(dat1.ltraj)) {
   total.path.df <- rbind(total.path.df, 
                          data.frame(dat1.ltraj[[i]], id = attr(dat1.ltraj[[i]], "id")))

total.path.df$distperday <- total.path.df$dist / (total.path.df$dt/60/60/24)

path.summary <- aggregate(distperday~id, data = total.path.df, FUN = mean)
path.summary$sd <- aggregate(distperday~id, data = total.path.df, FUN = sd)$distperday

# Make plot. Choose the dataframe (data) and aesthetics (aes; for the x and y)
path.plot <- ggplot(data = path.summary, aes(x = id, y = distperday, colour = id)) + 
  geom_point(size = 3) + # add points
  geom_errorbar(aes(ymax = distperday + sd, ymin = distperday - sd), width = 0.2) + # adds error bars
  labs(x = "Animal number", 
       y = "Mean distance travelled per day (m)" ) + # Axis labels
  theme_classic() + # Make plot black and white with no background grid
  theme(legend.position = "none")
path.plot # call plot

This topic was automatically closed 42 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.