Search code examples
rgeospatialspatial

Error with nesting GPS data and doing amt analysis


https://alaska.usgs.gov/products/data.php?dataid=612: Link for data, I am using the GPS location dataset.

I am running through the amt package vignette on some other GPS tracking data. I have run through the vignette data as well with no issue. I keep getting stuck at the nesting step, something appears to be wrong with how the data is being nested. I am also very stumped because inspecting the structures of the vignette data, and, my data they look the same. Below is the code I am using, and below that is the structure of my data. I have tried using subsets of the data without nesting and seem to have some luck, but the issue seems to be in the amt functions pulling the correct columns.

    #' Load libraries

library(sf)
library(lubridate)
library(raster)
library(move)
library(amt) 
library(tibble)
library(dplyr)


#' ### Load data
polarBear_GPS <- polarBear_GPSLocation_westHudsonBay_2019_2022
View(polarBear_GPS)

ind<-complete.cases(polarBear_GPS[,c("Datetime", "Longitude", "Latitude")])
polarBear_GPS<-polarBear_GPS[ind==TRUE,]

# Remove NA values from Datetime
polarBear_GPS <- polarBear_GPS[!is.na(polarBear_GPS$Datetime), ]

# Check for NA values again, should return 0
sum(is.na(polarBear_GPS$Datetime))  # Should return 0

#' Make timestamp a date/time variable
polarBear_GPS$Datetime <- as.POSIXct(polarBear_GPS$Datetime, format="%m/%d/%Y %H:%M:%S", tz="UTC")


#' We can also use lat, long, which will allow us to determine
#' time of day 
# Create the track
# Create the track with a different CRS
trk1 <- make_track(
  polarBear_GPS,
  .x = Longitude,
  .y = Latitude,
  .t = Datetime,
  id = Bear,
  crs = st_crs(4326)  # WGS 84
)


# Now it is easy to calculate day/night with either movement track
trk1 <- trk1 %>% time_of_day()

#' Now, we can transform back to geographic coordinates
trk1 <- transform_coords(trk1, crs_from = 4326, crs_to =4326 )


#' Or, we can add a columns to each nested column of data using purrr::map
trk2 <- trk1 %>% nest(data = -id)

  trk3 = trk2 %>% mutate(dir_abs = purrr:::map(data, direction_abs,full_circle=TRUE, zero="N"), 
                         dir_rel = purrr:::map(data, direction_rel), 
                         sl = purrr:::map(data, step_lengths),
                         nsd_=purrr:::map(data, nsd))

The error I am getting is after the nesting trying to run the functions on trk2

   str(trk1)
    Classes ‘track_xyt’, ‘track_xy’, ‘spec_tbl_df’, ‘tbl_df’, ‘tbl’ and 'data.frame':   118858 obs. of  5 variables:
 $ x_  : num  -93.2 -93.2 -93.2 -93.2 -93.2 ...
 $ y_  : num  58.8 58.8 58.8 58.8 58.8 ...
 $ t_  : POSIXct, format: "2019-08-26 20:20:11" "2019-08-26 20:25:10" "2019-08-26 20:30:09" ...
 $ id  : chr  "X17517" "X17517" "X17517" "X17517" ...
 $ tod_: Factor w/ 2 levels "day","night": 1 1 1 1 1 1 1 1 1 1 ...
 - attr(*, "spec")=List of 3
  ..$ cols   :List of 4
  .. ..$ Bear     : list()
  .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
  .. ..$ Datetime : list()
  .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
  .. ..$ Latitude : list()
  .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
  .. ..$ Longitude: list()
  .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
  ..$ default: list()
  .. ..- attr(*, "class")= chr [1:2] "collector_guess" "collector"
  ..$ delim  : chr ","
  ..- attr(*, "class")= chr "col_spec"
 - attr(*, "problems")=<externalptr> 
 - attr(*, "crs_")= num 4326


    

 str(trk2)
        nstd_trc [20 × 2] (S3: nested_track/tbl_df/tbl/data.frame)
         $ id  : chr [1:20] "X17517" "X19911" "X33824" "X33939" ...
         $ data:List of 20
          ..$ : trck_xyt [5,435 × 4] (S3: track_xyt/track_xy/spec_tbl_df/tbl_df/tbl/data.frame)
          .. ..$ x_  : num [1:5435] -93.2 -93.2 -93.2 -93.2 -93.2 ...
          .. ..$ y_  : num [1:5435] 58.8 58.8 58.8 58.8 58.8 ...
          .. ..$ t_  : POSIXct[1:5435], format: "2019-08-26 20:20:11" "2019-08-26 20:25:10" "2019-08-26 20:30:09" "2019-08-26 20:35:09" ...
          .. ..$ tod_: Factor w/ 2 levels "day","night": 1 1 1 1 1 1 1 1 1 1 ...
          .. ..- attr(*, "spec")=List of 3
          .. .. ..$ cols   :List of 4
          .. .. .. ..$ Bear     : list()
          .. .. .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
          .. .. .. ..$ Datetime : list()
          .. .. .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
          .. .. .. ..$ Latitude : list()
          .. .. .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
          .. .. .. ..$ Longitude: list()
          .. .. .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
          .. .. ..$ default: list()
          .. .. .. ..- attr(*, "class")= chr [1:2] "collector_guess" "collector"
          .. .. ..$ delim  : chr ","
          .. .. ..- attr(*, "class")= chr "col_spec"
          .. ..- attr(*, "problems")=<externalptr> 
          .. ..- attr(*, "crs_")= num 4326

Error code is: Error in mutate(): ℹ In argument: dir_abs = purrr:::map(data, direction_abs, full_circle = TRUE, zero = "N"). Caused by error in purrr:::map(): ℹ In index: 1. Caused by error in h(): ! error in evaluating the argument 'y' in selecting a method for function 'atan2': argument "y" is missing, with no default


Solution

  • Couple of issues that might be causing your issue:

    1. package versions need updating
    2. using transform_coords() on data that are already have the target CRS e.g. WGS84/EPSG:4326. See the metadata at the Alaska Science Center download link
    3. some manipulation was applied to the polarBear_GPSLocation_westHudsonBay_2019_2022 object as there was no error loading the csv file directly
    4. potential conflict between packages (unlikely though)

    These issues were not/could not be tested, so cannot confirm. These stated issues are unlikely to be causing a problem (except issue 3 potentially). However, to rule out as many causes as possible, start from a fresh R sessions and run the below code verbatim (including not loading any other packages other than those stated).

    Note also that the code you posted does not include a step to check for duplicate timestamps (which need to be removed if they exist). Code to check and remove duplicates is included in this reprex. None were found, and no NAs were present either, so the source data are clean.

    library(sf)
    library(amt) 
    library(dplyr)
    library(purrr)
    
    # Load data from working directory, previously unzipped and downloaded from
    # https://alaska.usgs.gov/data1/polarBear/polarBear_onLand_westHudsonBay_pagano/polarBear_GPSLocation_westHudsonBay_2019-2022.zip
    polarBear_GPS <- read.csv("polarBear_GPSLocation_westHudsonBay_2019-2022.csv")
    
    # Check for NA values, 0 == no NA values in df
    sum(is.na(polarBear_GPS))
    # [1] 0
    
    ### Skip following if previous step returns 0
    
    # ind <- complete.cases(polarBear_GPS[, c("Datetime", "Longitude", "Latitude")])
    # 
    # polarBear_GPS <- polarBear_GPS[ind == TRUE, ]
    # 
    # # Remove NA values from Datetime
    # polarBear_GPS <- polarBear_GPS[!is.na(polarBear_GPS$Datetime), ]
    
    ###
    
    # Make Datetime a date/time variable
    polarBear_GPS$Datetime <- as.POSIXct(polarBear_GPS$Datetime, format="%m/%d/%Y %H:%M:%S", tz = "UTC")
    
    # Check for duplicated timestamps per bear
    polarBear_GPS |>
      summarise(ts_dupes = any(duplicated(Datetime)), .by = Bear)
    #      Bear ts_dupes
    # 1  X17517    FALSE
    # 2  X19911    FALSE
    # 3  X33823    FALSE
    # 4  X33824    FALSE
    # 5  X33935    FALSE
    # 6  X33939    FALSE
    # 7  X33653    FALSE
    # 8  X33934    FALSE
    # 9  X33928    FALSE
    # 10 X33936    FALSE
    # 11 X33938    FALSE
    # 12 X33991    FALSE
    # 13 X33954    FALSE
    # 14 X33851    FALSE
    # 15 X32415    FALSE
    # 16 X33410    FALSE
    # 17 X33712    FALSE
    # 18 X19842    FALSE
    # 19 X33302    FALSE
    # 20 X32422    FALSE
    
    # If any return true, run following step, else skip
    polarBear_GPS <- polarBear_GPS |>
      distinct(Datetime, .keep_all = TRUE, .by = Bear)
    
    # Create the track with correct CRS (see metadata at download link above)
    trk1 <- make_track(
      polarBear_GPS,
      .x = Longitude,
      .y = Latitude,
      .t = Datetime,
      id = Bear,
      crs = st_crs(4326)  # WGS 84
    )
    
    # Calculate day/night
    trk1 <- trk1 |> time_of_day()
    
    # Add columns to each nested column of data using purrr::map()
    trk2 <- trk1 |> nest(data = -id)
    
    trk3 <- trk2 |>
      mutate(dir_abs = map(data, direction_abs, full_circle = TRUE, zero = "N"), 
             dir_rel = map(data, direction_rel), 
             sl = map(data, step_lengths),
             nsd_ = map(data, nsd))
    
    trk3
    # A tibble: 20 × 6
    #    id     data                   dir_abs       dir_rel       sl            nsd_         
    #    <chr>  <list>                 <list>        <list>        <list>        <list>       
    #  1 X17517 <trck_xyt [5,435 × 4]> <dbl [5,435]> <dbl [5,435]> <dbl [5,435]> <dbl [5,435]>
    #  2 X19911 <trck_xyt [5,381 × 4]> <dbl [5,381]> <dbl [5,381]> <dbl [5,381]> <dbl [5,381]>
    #  3 X33824 <trck_xyt [5,818 × 4]> <dbl [5,818]> <dbl [5,818]> <dbl [5,818]> <dbl [5,818]>
    #  4 X33939 <trck_xyt [5,468 × 4]> <dbl [5,468]> <dbl [5,468]> <dbl [5,468]> <dbl [5,468]>
    #  5 X33823 <trck_xyt [5,688 × 4]> <dbl [5,688]> <dbl [5,688]> <dbl [5,688]> <dbl [5,688]>
    #  6 X33934 <trck_xyt [6,080 × 4]> <dbl [6,080]> <dbl [6,080]> <dbl [6,080]> <dbl [6,080]>
    #  7 X33935 <trck_xyt [5,690 × 4]> <dbl [5,690]> <dbl [5,690]> <dbl [5,690]> <dbl [5,690]>
    #  8 X33928 <trck_xyt [6,040 × 4]> <dbl [6,040]> <dbl [6,040]> <dbl [6,040]> <dbl [6,040]>
    #  9 X33936 <trck_xyt [6,037 × 4]> <dbl [6,037]> <dbl [6,037]> <dbl [6,037]> <dbl [6,037]>
    # 10 X33653 <trck_xyt [6,025 × 4]> <dbl [6,025]> <dbl [6,025]> <dbl [6,025]> <dbl [6,025]>
    # 11 X33938 <trck_xyt [5,977 × 4]> <dbl [5,977]> <dbl [5,977]> <dbl [5,977]> <dbl [5,977]>
    # 12 X33991 <trck_xyt [6,002 × 4]> <dbl [6,002]> <dbl [6,002]> <dbl [6,002]> <dbl [6,002]>
    # 13 X33954 <trck_xyt [6,301 × 4]> <dbl [6,301]> <dbl [6,301]> <dbl [6,301]> <dbl [6,301]>
    # 14 X33851 <trck_xyt [5,985 × 4]> <dbl [5,985]> <dbl [5,985]> <dbl [5,985]> <dbl [5,985]>
    # 15 X32415 <trck_xyt [5,969 × 4]> <dbl [5,969]> <dbl [5,969]> <dbl [5,969]> <dbl [5,969]>
    # 16 X33410 <trck_xyt [6,050 × 4]> <dbl [6,050]> <dbl [6,050]> <dbl [6,050]> <dbl [6,050]>
    # 17 X33712 <trck_xyt [6,581 × 4]> <dbl [6,581]> <dbl [6,581]> <dbl [6,581]> <dbl [6,581]>
    # 18 X19842 <trck_xyt [6,464 × 4]> <dbl [6,464]> <dbl [6,464]> <dbl [6,464]> <dbl [6,464]>
    # 19 X33302 <trck_xyt [5,889 × 4]> <dbl [5,889]> <dbl [5,889]> <dbl [5,889]> <dbl [5,889]>
    # 20 X32422 <trck_xyt [5,978 × 4]> <dbl [5,978]> <dbl [5,978]> <dbl [5,978]> <dbl [5,978]>