Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

In R, I'd like to calculate the straight-line distance between each capture of an animal in my dataset - no need to take into account the curvature of the earth. I have a dataset that looks like this:

record.nbr<- c(1:8)
individual<-  c(1,2,1,2,1,3,1,2)
x<-c(167685,167945,167685,153985,167685,158675,167645,167667)
y<-c(9876548,9879248,9876838,9596548,9926548,9878578,9876548,9166548)
julian.date<-c(125,126,127,127,128,129,130,130)
captures<-data.frame(cbind(record.nbr, individual, x, y, julian.date))

Here each "individual" represents a unique animal, and x/y points represent locations where the animals were captured. x/y points are UTM coordinates. Some individuals are caught many times, while other individuals are only captured once.

I'd like to calculate the distance (and the mean date) between recaptures by individual. In the output table, each row would summarize the distance between consecutive recaptures of an individual, plus the mean date between recaptures, like so:

individual first.rec  second.rec  distance  mean.date
1          1             3        V         126
1          3             5        W         127.5
1          5             7        X         129
2          2             4        Y         126.5
3          4             6        Z         128
share|improve this question
add comment

1 Answer

up vote 5 down vote accepted

One way to do this is using ddply from the plyr package:

require(plyr)
# split up captures by the unique individual id for processing
ddply(captures, "individual", function(df) {
  # single captures don't have any dist/time changes
  if(nrow(df)==1) {
    return(data.frame(start=NA,
                      end=NA,
                      dist=NA,
                      mean.time=NA))
  }

  # for each pair of consecutive displacement, calculate dist and mean time
  out <- sapply(1:(nrow(df)-1), function(i) {
    d <- dist(df[i:(i+1),3:4])
    t <- mean(df[i:(i+1),5])
    c(d,t)
  })
  out <- t(out)

  # reports results, adding the starting and ending record number
  # for each displacement
  data.frame(start=head(df$record.nbr,-1),
             end=tail(df$record.nbr, -1),
             dist=out[,1],
             mean.time=out[,2])
})

Which results in:

  individual start end      dist mean.time
1          1     1   3    290.00     126.0
2          1     3   5  49710.00     127.5
3          1     5   7  50000.02     129.0
4          2     2   4 283044.47     126.5
5          2     4   8 430217.62     128.5
6          3    NA  NA        NA        NA

The equivalent can be done using base tapply in R, however I generally find the ddply to be cleaner.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.