0
votes

I am hoping someone can tell me where I am going wrong...I am trying to calculate distance between a point and the one one the previous row; locations are in lat/longs, WGS84). I have worked out was is undoubtedly a highly inelegant way to do this with the following code:

df200$Long.prev <- c(NA,df200$AvgLong[1:(length(df200$AvgLong)-1)])
df200$Lat.prev <- c(NA,df200$AvgLat[1:(length(df200$AvgLat)-1)])
library(geosphere)
library(raster)
p1 <- SpatialPointsDataFrame(df200[c("AvgLong","AvgLat")],     data=data.frame(id=df200$Animal),proj4string=CRS("+proj=longlat +datum=WGS84"))
p2 <- SpatialPointsDataFrame(df200[c("Long.prev","Lat.prev")], data=data.frame(id=df200$Animal),proj4string=CRS("+proj=longlat +datum=WGS84"))
distance <- distGeo (p1, p2)
distance.VE <- distVincentyEllipsoid(p1,p2)
df200$distance.from.previous <- as.numeric(distance)
df2$distance.from.previous.VE <-as.numeric(distance.VE) 

This works on my initial dataframe just fine; I get reasonable distance values (compared to what I roughly get with the QGIS ruler tool) and equal values from distGeo and distVincentyEllipsoid. Here is an example of the distance portion of the output (as expected):

distance.from.previous distance.from.previous.VE

460.8000 460.8000
725.1920 725.1920
284.0190 284.0190
861.2344 861.2344
828.64791 828.64791

However, really, I want to filter out bad GPS locations before I do the distance calculations, so I first apply this:

df2 <- with(df2, df2[AvgHDOP <=2 & (AvgAlt >=0 & AvgAlt <=75),])

However, once I have done that, the distance calculations no longer work properly. Instead, I get odd/incorrect values, including negatives for distGeo, as can be seen here:

distance.from.previous distance.from.previous.VE
4.415878e-14 0.0000
-1.719159e-14 0.0000
2.443902e-13 0.0000
9.951547e+02 995.1547
9.865199e+02 986.5199

In this instance, due to filtering, the first two points equate to the 4th and 5th in the above example, so the distance output should be 828.65m. However, something has clearly gone very wrong, and I can't for the life of me figure it out! Any help? Also, should I be concerned that I get a distance value for the first line, since the Lat.prev and Long.prev for that row are NA?

I do get some error messages (all due to the initial NAs, I believe), but I get the same errors in both the first case where it works fine and the second where it gives me odd results.

p2 <- SpatialPointsDataFrame(df2[c("Long.prev","Lat.prev")], data=data.frame(id=df2$Animal),proj4string=CRS("+proj=longlat +datum=WGS84"))
Error in .local(obj, ...) : NA values in coordinates
distance <- distGeo (p1, p2)
Warning message: In cbind(p1[, 1], p1[, 2], p2[, 1], p2[, 2]) : number of rows of result is not a multiple of vector length (arg 3)
distance.VE <- distVincentyEllipsoid(p1,p2)
Warning message: In cbind(p1[, 1], p1[, 2], p2[, 1], p2[, 2], as.vector(a), as.vector(b), : number of rows of result is not a multiple of vector length > (arg 3)

Any help much appreciated!

1
what are you trying to do when you use df2 <- with(df2, df2[AvgHDOP <=2 & (AvgAlt >=0 & AvgAlt <=75),]), what's AvgHDOP? - MLavoie

1 Answers

1
votes

Use a simplified example, with data (the data you are actually using that lead to this problem). The negative values that you find are really zeros.

It is almost certainly your pre-processing. Perhaps here:

df2 <- with(df2, df2[AvgHDOP <=2 & (AvgAlt >=0 & AvgAlt <=75),])

which probably should be

df2 <- df2[AvgHDOP <=2 & (AvgAlt >=0 & AvgAlt <=75),]

although I am not sure if that matters here.

Here is a simple reproducible example that you might use to better illustrate your problem.

library(geosphere)

set.seed(0)
long <- 360*runif(10)-180
lat <- 180*runif(10)-90
p1 <- cbind(long, lat)

long.prev <- c(NA,long[1:(length(long)-1)])
lat.prev <-  c(NA,lat[1:(length(lat)-1)])
p2 <- cbind(long.prev, lat.prev)

distance <- distGeo(p1, p2)
round(distance / 1000)