3

Overall task that i would like to solve: using the shift function i would like to calculate the mean bearing geosphere::bearing(p1, p2,a=6378137, f=1/298.257223563) of previos 3 points (lag) and compare it to the bearing of following 3 points (lead).

That means

  1. calculate bearing betwenn all 3 points (lag)
mean(bearing(point1,point2),bearing(point1,point3),bearing(point2,point3))

and between next 3 points (lead).

mean(bearing(point4,point5),bearing(point4,point6)bearing(point5,point6))
  1. calculate mean value for those bearings
  2. if mean bearing of first (lag) 3 points is to different (bassiclaiy abs(dif)) to next 3 (lead) points , discard the (lead) 3 points.

What is the best way to do so? It does not have to be a shift function but i thought it may be fitting. I just dont want to write loops. Here is an example path:

path<-structure(list(counter = 1:24, lon = c(11.83000844, 11.82986091, 
11.82975536, 11.82968137, 11.82966589, 11.83364579, 11.83346388, 
11.83479848, 11.83630055, 11.84026754, 11.84215965, 11.84530872, 
11.85369492, 11.85449806, 11.85479096, 11.85888555, 11.85908087, 
11.86262424, 11.86715538, 11.86814045, 11.86844252, 11.87138302, 
11.87579809, 11.87736704), lat = c(48.10980039, 48.10954023, 
48.10927434, 48.10891122, 48.10873965, 48.09824039, 48.09526792, 
48.0940306, 48.09328273, 48.09161348, 48.09097173, 48.08975325, 
48.08619985, 48.08594538, 48.08576984, 48.08370241, 48.08237208, 
48.08128785, 48.08204915, 48.08193609, 48.08186387, 48.08102563, 
48.07902278, 48.07827614)), row.names = c(NA, -24L), class = c("data.table", 
"data.frame"))

Thank you.

Andreas
  • 397
  • 4
  • 18
  • 37

1 Answers1

2

I'm not convinced this will help with the other question (R: Detect a "main" Path and remove or filter the GPS trace maybe using a kernel?) but this is a way to find the average for the following two points.

First you expand_grid to get all pairs, then you filter down to the pairs you are interested in. Then you create a new data frame which filters further such that for each counter you have the three bearings, at which point you can take the average.

First: I want to have each lat/lon pair to be matched with every other lat/lon pair. For this i use expand_grid, and want to expand our data with itself. This fails on it's face because you need unique names for each argument of expand_grid. Thus I setNames prior to the call.

Then: We only want a subset of those pairs of points. In particular, we want any case where the counter_2 is less than the counter + 2 (eg. you want counter = 1 and counter_2 %in% c(2,3), counter = 2 and counter_2 %in% c(3,4)...)

You then need to go rowwise through the dataset and calculate the bearing for each row. We call this dataframe data_tmp.

Then we do a map and filtration to get the rows needed for each value of counter.

library(tidyverse)

data_tmp <- path %>% 
  as_tibble() %>% 
  (function(X)expand_grid(X, 
                          X %>% setNames(c("counter_2", "lon_2", "lat_2")))) %>% 
  filter(counter_2 <= counter + 2 & counter_2 > counter) %>%
  rowwise() %>%
  mutate(bearing = geosphere::bearing(c(lon, lat), c(lon_2,lat_2))) %>%
  ungroup()

three_grouped <- tibble(counter = 1:max(path$counter)) %>%
  mutate(dataz = map(.x = counter, ~ data_tmp %>% 
                      slice(which(data_tmp$counter_2 %in% 
                                    data_tmp$counter_2[data_tmp$counter == .x] &
                                    data_tmp$counter <= .x + 1 &
                                    data_tmp$counter >= .x)))) 

three_grouped %>%
  mutate(average_bearing = map_dbl(dataz, ~ mean(.x$bearing)))
BrianLang
  • 831
  • 4
  • 14
  • Thank you brian: my thinking behind this is the following: In my code sometimes a condition accures where my path finding algo goes mistakenly in one direction then corrects and goes the same way back. So in theory to filter out this the bearing would be complete oposite of the way in one and the other direction. This condition im trying to cach. Thank you very much for the suggestion i´l try it right away. – Andreas Oct 06 '20 at 11:56
  • Yes, that was my instinct for the question as well. I think you'll have to run such a filtration iteratively on the entire track. – BrianLang Oct 06 '20 at 12:43
  • Yes i did that. Currently trying to undersrand what is happening in your code :) – Andreas Oct 06 '20 at 12:43
  • ther is some problem with this code counter dataz average_bearing 1 1 -27.3 2 2 NaN 3 3 NaN 4 4 NaN it produces NaN for avg bearing and calculation takes sadly a long time. – Andreas Oct 06 '20 at 13:16
  • Can you explain what you called and what it is that you're pasting into the comments? I can't tell from what you've posted. – BrianLang Oct 06 '20 at 13:17
  • Sorry its not possible to format in comments: its a print out of three_grouped after the last line of your code. Bearing is printed as NaN – Andreas Oct 06 '20 at 13:19
  • For which value of counter is it returned as a NaN? This would be expected at the end of your data. Does it work on the sample data that you provided? it looks like you're trying it now on a larger dataset (which i haven't seen). – BrianLang Oct 06 '20 at 13:19
  • Its in the begining of the tible. First value is -27 and every other one is NaN. – Andreas Oct 06 '20 at 13:20
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/222595/discussion-between-brianlang-and-andreas). – BrianLang Oct 06 '20 at 13:22