1

I want to use R to find out the point locations at which my vehicle (equiped with GPS) started to turn. The data contains coordinates and time information. I have sort my data based on time sequence:

 time_stamp <- as.POSIXct(paste(field$Date, field$Time), format="%d/%m/%Y %H:%M:%S")
 field <- data.frame(field,time_stamp)
 field <- field[order(field$time_stamp),] 

Then I borrow the codes from post below to calculate the angles of each three sequential points: https://stackoverflow.com/questions/11184381/calculating-angle-from-latitude-and-longitude

And modified it a little bit.

# define coordinates 

coordinates(field) <- c("Longitude", "Latitude")
proj4string(field) <- CRS("+init=epsg:4326")

# calculate angles

trackAngle <- function(xy) {
angles <- abs(c(trackAzimuth(xy), 0) -
              c(0, rev(trackAzimuth(xy[nrow(xy):1, ]))))
angles <- ifelse(angles > 180, 360 - angles, angles)
angles[is.na(angles)] <- 180
angles[-c(1, length(angles))]
}

ang <- trackAngle(field@coords)

# Just to make it the same length as my dataset
# I inserted the first and the last angles to the vector 

ang <- c(ang[1],ang,ang[1]) 

Now I am thinking to use if-else statement, says if at this point the angle is bigger than 20 degree compared the last point, then this point will be classified as the point of turning.

new_df <- data.frame(field,ang1)
new_column <- 1:nrow(new_df)

for(i in 1:nrow(new_df))
{  
  angle_changes <- ang1[i+1]-ang1[i]
  if (angle_changes>20)
   {new_column[i] <- 'turn'}
  else
   {new_column[i] <- 'not_turn'}
 }
Error in if (angle_changes > 20) { : 
  missing value where TRUE/FALSE needed

Is there a simpler and faster way of achieving this, without calculating all angles first?

For reproducible example, I selected the first 20 rows. The raw dataset has ~63,000 obs.

     field1
           Longitude  Latitude
     49221   175.723 -37.82931
     49222   175.723 -37.82931
     49223   175.723 -37.82931
     49230   175.723 -37.82931
     49248   175.723 -37.82931
     49272   175.723 -37.82931
     49309   175.723 -37.82932
     49324   175.723 -37.82932
     49337   175.723 -37.82932
     49347   175.723 -37.82932
     49357   175.723 -37.82932
     49367   175.723 -37.82932
     49380   175.723 -37.82932
     49389   175.723 -37.82932
     49393   175.723 -37.82932
     49400   175.723 -37.82932
     49411   175.723 -37.82932
     49417   175.723 -37.82932
     49430   175.723 -37.82932
     49434   175.723 -37.82932

I compared trip package trackAngle with the defined trackAngle. The former output 18 results NA NA 172.0851 174.9314 179.6634 172.2936 170.6603 178.0629 176.5133 178.0556 178.0443 173.4078 177.9946 179.6743 178.1043 178.5513 177.2740 177.2740,

the later output 180.0000 180.0000 172.0851 174.9314 179.6634 172.2936 170.6603 178.0629 176.5133 178.0556 178.0443 173.4078 177.9946 179.6743 178.1043 178.5513 177.2740 177.2740.

  • You can use diff(ang) to avoid looping, and fwiw there is an equivalent trip::trackAngle function – mdsumner Sep 10 '16 at 12:08
  • thanks, I wonder why trip::trackAngle generates 2429 NA's for my dataset while the defined trackAngle function doesn't. @mdsumner – Gorden Jiang Sep 11 '16 at 23:10
  • reproducible example? – mdsumner Sep 12 '16 at 4:27
  • Please find my edited question @mdsumner – Gorden Jiang Sep 13 '16 at 2:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.