1

I have animal survey data from transects. Transects are divided into sections. There are lat/lon data for the start/endpoints of some sections but not others, and I want to calculate the start/endpoints for sections where these values are missing. Missing start/endpoints should be calculated using the section bearing (degrees), section length (m).

Example data:

Section StartLon StartLat EndLon EndLat Bearing Length
1 -132.4053 53.00704 -132.4053 53.00714 360 5
2 -132.4053 53.00714 NA NA 360 10

I'm trying to use destPoint (geosphere) to calculate the missing start/endpoints (NAs). The output of destPoint looks like:

        lon       lat
[1,] -132.4053 53.00701

My code:

data %>% 
  mutate(EndLon = if_else(is.na(EndLon), destPoint(c(StartLon, StartLat), Bearing, Length), EndLon))

data %>% 
  mutate(EndLat = if_else(is.na(EndLat), destPoint(c(StartLon, StartLat), Bearing, Length), EndLat))

My code gives this error:

Error: Problem with `mutate()` input `test`.
x Wrong length for a vector, should be 2
i Input `test` is `if_else(...)`

I think the error is because the output of destPoint is two values (lon and lat), and the mutated column can only hold one value. Maybe there's a way to use select() so that only lon or lat goes into the mutated column?

Hoping for a dplyr solution.

sbliss
  • 87
  • 2

1 Answers1

0

We may use rowwise

library(dplyr)
library(geosphere)
data %>%
    rowwise %>%
    mutate(EndLon = if(is.na(EndLon)) 
       destPoint(c(StartLon, StartLat), Bearing, Length)[, 'lon'] else EndLon) %>%
    ungroup

-output

# A tibble: 2 x 7
#  Section StartLon StartLat EndLon EndLat Bearing Length
#    <int>    <dbl>    <dbl>  <dbl>  <dbl>   <int>  <int>
#1       1    -132.     53.0  -132.   53.0     360      5
#2       2    -132.     53.0  -132.   NA       360     10

data

data <- structure(list(Section = 1:2, StartLon = c(-132.4053, -132.4053
), StartLat = c(53.00704, 53.00714), EndLon = c(-132.4053, NA
), EndLat = c(53.00714, NA), Bearing = c(360L, 360L), Length = c(5L, 
10L)), class = "data.frame", row.names = c(NA, -2L))

The issue would be that c(StartLon, StartLat) would concatenate the whole column values from both of those column, and thereby the length of one of the arguments for if_else becomes different in length than the rest. If we do the rowwise, it is grouped by row and we can use if/else (which requires a input logical expression of length 1)

akrun
  • 874,273
  • 37
  • 540
  • 662