Skip to contents

This vignette shows how to get a species record table as returned by camtrapR’s function recordTable starting from a camera trap data package.

Setup

Load packages:

library(camtraptor)
library(lubridate)
#> Loading required package: timechange
#> 
#> Attaching package: 'lubridate'
#> The following objects are masked from 'package:base':
#> 
#>     date, intersect, setdiff, union
library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union

By loading package camtraptor, a camera trap data package called camtraptor is made available. This data package contains camera trap data of musk rats and coypus. We will use this variable from now on.

Species record table

The camtrapR’s function recordTable() generates:

a record table from camera trap images or videos

At a certain extent the aggregation of media (e.g. images) into observations is already done in a camera trap data package.

If we consider that all observations are independent, then, it will be sufficient to run the following:

get_record_table(mica)
#> # A tibble: 17 × 11
#>    Station  Species DateTimeOriginal    Date       Time  delta…¹ delta…² delta…³
#>    <chr>    <chr>   <dttm>              <date>     <chr>   <dbl>   <dbl>   <dbl>
#>  1 B_DL_va… Anas p… 2020-07-31 04:43:33 2020-07-31 04:4…       0      0      0  
#>  2 B_DL_va… Anas p… 2020-08-02 05:00:14 2020-08-02 05:0…  173801   2897.    48.3
#>  3 B_DL_va… Anas p… 2020-08-03 05:09:12 2020-08-03 05:0…   86938   1449.    24.1
#>  4 B_DL_va… Anas p… 2020-08-04 05:04:09 2020-08-04 05:0…   86097   1435.    23.9
#>  5 B_DL_va… Anas s… 2020-07-29 05:46:48 2020-07-29 05:4…       0      0      0  
#>  6 B_DL_va… Anas s… 2020-07-30 04:29:31 2020-07-30 04:2…   81763   1363.    22.7
#>  7 B_DL_va… Anas s… 2020-08-05 05:02:01 2020-08-05 05:0…  520350   8672.   145. 
#>  8 B_DM_va… Ardea   2021-04-05 19:08:33 2021-04-05 19:0…       0      0      0  
#>  9 B_DM_va… Ardea   2021-04-11 19:43:09 2021-04-11 19:4…  520476   8675.   145. 
#> 10 B_DM_va… Ardea … 2021-03-27 20:38:18 2021-03-27 20:3…       0      0      0  
#> 11 B_DL_va… Castor… 2020-06-19 22:05:55 2020-06-19 22:0…       0      0      0  
#> 12 Mica Vi… Homo s… 2019-10-23 10:19:44 2019-10-23 10:1…       0      0      0  
#> 13 B_DL_va… Martes… 2020-06-28 22:01:12 2020-06-28 22:0…       0      0      0  
#> 14 B_DL_va… Mustel… 2020-06-19 22:31:51 2020-06-19 22:3…       0      0      0  
#> 15 B_DL_va… Mustel… 2020-06-23 23:33:53 2020-06-23 23:3…  349322   5822.    97.0
#> 16 B_DL_va… Mustel… 2020-06-28 23:33:16 2020-06-28 23:3…  431963   7199.   120. 
#> 17 B_DL_va… Vulpes… 2020-06-26 02:09:25 2020-06-26 02:0…       0      0      0  
#> # … with 3 more variables: delta.time.days <dbl>, Directory <list>,
#> #   FileName <list>, and abbreviated variable names ¹​delta.time.secs,
#> #   ²​delta.time.mins, ³​delta.time.hours

The function returns the same columns as the camtrapR’s function recordTable(). The following mapping is applied:

column name output description
Station the station name as provided by argument stationCol (default: locationName). It has to be a column of deployments
Species scientific_name column in observations
DateTimeOriginal the timestamp column in observations
Date the date from timestamp
Time the time part from timestamp
delta.time.secs the elapsed time in seconds between two (independent) observations
delta.time.mins the elapsed time in minutes between two (independent) observations
delta.time.hours the elapsed time in hours between two (independent) observations
delta.time.days the elapsed time in days between two (independent) observations
Directory a list with file paths as stored in column file_path of media
FileName a list with file paths as stored in column file_path of media

The following remarks are both valid for camtrapR’s function recordTable() and the function get_record_table() of this package: 1. observations are grouped by station and species 2. observations of unidentified animals are removed 2. the elapsed time of the first observation (record) of a species at a certain station is set to 0 by default

Temporal independence

As described in Chapter 3 of camptrapR documentation, we could filter observations using an adjustable criterion for temporal independence between subsequent records of the same species in an attempt to remove non-independent records. As for recordTable(), this is achieved via argument minDeltaTime, defined as the minimum time difference (in minutes) between two records of the same species at the same station which are to be considered independent. As shown above, the default is 0, causing the function to return all records.

Again, as for recordTable(), we provide an argument, deltaTimeComparedTo, to further control how independence between records is assessed. Setting it to “lastRecord” returns only records taken minDeltaTime minutes after the last record, i.e. minDeltaTime minutes after timestamp of the last recorded media file. Example with minDeltaTime = 60 (1 hour):

get_record_table(mica, 
                 minDeltaTime = 60, 
                 deltaTimeComparedTo = "lastRecord")
#> # A tibble: 17 × 11
#>    Station  Species DateTimeOriginal    Date       Time  delta…¹ delta…² delta…³
#>    <chr>    <chr>   <dttm>              <date>     <chr>   <dbl>   <dbl>   <dbl>
#>  1 B_DL_va… Anas p… 2020-07-31 04:43:33 2020-07-31 04:4…       0      0      0  
#>  2 B_DL_va… Anas p… 2020-08-02 05:00:14 2020-08-02 05:0…  173801   2897.    48.3
#>  3 B_DL_va… Anas p… 2020-08-03 05:09:12 2020-08-03 05:0…   86938   1449.    24.1
#>  4 B_DL_va… Anas p… 2020-08-04 05:04:09 2020-08-04 05:0…   86097   1435.    23.9
#>  5 B_DL_va… Anas s… 2020-07-29 05:46:48 2020-07-29 05:4…       0      0      0  
#>  6 B_DL_va… Anas s… 2020-07-30 04:29:31 2020-07-30 04:2…   81763   1363.    22.7
#>  7 B_DL_va… Anas s… 2020-08-05 05:02:01 2020-08-05 05:0…  520350   8672.   145. 
#>  8 B_DM_va… Ardea   2021-04-05 19:08:33 2021-04-05 19:0…       0      0      0  
#>  9 B_DM_va… Ardea   2021-04-11 19:43:09 2021-04-11 19:4…  520476   8675.   145. 
#> 10 B_DM_va… Ardea … 2021-03-27 20:38:18 2021-03-27 20:3…       0      0      0  
#> 11 B_DL_va… Castor… 2020-06-19 22:05:55 2020-06-19 22:0…       0      0      0  
#> 12 Mica Vi… Homo s… 2019-10-23 10:19:44 2019-10-23 10:1…       0      0      0  
#> 13 B_DL_va… Martes… 2020-06-28 22:01:12 2020-06-28 22:0…       0      0      0  
#> 14 B_DL_va… Mustel… 2020-06-19 22:31:51 2020-06-19 22:3…       0      0      0  
#> 15 B_DL_va… Mustel… 2020-06-23 23:33:53 2020-06-23 23:3…  349322   5822.    97.0
#> 16 B_DL_va… Mustel… 2020-06-28 23:33:16 2020-06-28 23:3…  431963   7199.   120. 
#> 17 B_DL_va… Vulpes… 2020-06-26 02:09:25 2020-06-26 02:0…       0      0      0  
#> # … with 3 more variables: delta.time.days <dbl>, Directory <list>,
#> #   FileName <list>, and abbreviated variable names ¹​delta.time.secs,
#> #   ²​delta.time.mins, ³​delta.time.hours

Setting deltaTimeComparedTo to “lastIndependentRecord” returns only records taken minDeltaTime minutes after the last independent record, i.e. minDeltaTime minutes after timestamp of the last observation. Example with minDeltaTime = 60 (1 hour):

get_record_table(mica, 
                 minDeltaTime = 60, 
                 deltaTimeComparedTo = "lastIndependentRecord")
#> # A tibble: 17 × 11
#>    Station  Species DateTimeOriginal    Date       Time  delta…¹ delta…² delta…³
#>    <chr>    <chr>   <dttm>              <date>     <chr>   <dbl>   <dbl>   <dbl>
#>  1 B_DL_va… Anas p… 2020-07-31 04:43:33 2020-07-31 04:4…       0      0      0  
#>  2 B_DL_va… Anas p… 2020-08-02 05:00:14 2020-08-02 05:0…  173801   2897.    48.3
#>  3 B_DL_va… Anas p… 2020-08-03 05:09:12 2020-08-03 05:0…   86938   1449.    24.1
#>  4 B_DL_va… Anas p… 2020-08-04 05:04:09 2020-08-04 05:0…   86097   1435.    23.9
#>  5 B_DL_va… Anas s… 2020-07-29 05:46:48 2020-07-29 05:4…       0      0      0  
#>  6 B_DL_va… Anas s… 2020-07-30 04:29:31 2020-07-30 04:2…   81763   1363.    22.7
#>  7 B_DL_va… Anas s… 2020-08-05 05:02:01 2020-08-05 05:0…  520350   8672.   145. 
#>  8 B_DM_va… Ardea   2021-04-05 19:08:33 2021-04-05 19:0…       0      0      0  
#>  9 B_DM_va… Ardea   2021-04-11 19:43:09 2021-04-11 19:4…  520476   8675.   145. 
#> 10 B_DM_va… Ardea … 2021-03-27 20:38:18 2021-03-27 20:3…       0      0      0  
#> 11 B_DL_va… Castor… 2020-06-19 22:05:55 2020-06-19 22:0…       0      0      0  
#> 12 Mica Vi… Homo s… 2019-10-23 10:19:44 2019-10-23 10:1…       0      0      0  
#> 13 B_DL_va… Martes… 2020-06-28 22:01:12 2020-06-28 22:0…       0      0      0  
#> 14 B_DL_va… Mustel… 2020-06-19 22:31:51 2020-06-19 22:3…       0      0      0  
#> 15 B_DL_va… Mustel… 2020-06-23 23:33:53 2020-06-23 23:3…  349322   5822.    97.0
#> 16 B_DL_va… Mustel… 2020-06-28 23:33:16 2020-06-28 23:3…  431963   7199.   120. 
#> 17 B_DL_va… Vulpes… 2020-06-26 02:09:25 2020-06-26 02:0…       0      0      0  
#> # … with 3 more variables: delta.time.days <dbl>, Directory <list>,
#> #   FileName <list>, and abbreviated variable names ¹​delta.time.secs,
#> #   ²​delta.time.mins, ³​delta.time.hours

Exclude some species

Similar to recordTable(), the function get_record_table() allows you also to exclude some species. Both vernacular names and scientific names are allowed (case insensitive):

get_record_table(mica, exclude = c("grey heron", "Anas platyrhynchos", "mens"))
#> Scientific name of grey heron: Ardea cinerea
#> Scientific name of mens: Homo sapiens
#> # A tibble: 11 × 11
#>    Station  Species DateTimeOriginal    Date       Time  delta…¹ delta…² delta…³
#>    <chr>    <chr>   <dttm>              <date>     <chr>   <dbl>   <dbl>   <dbl>
#>  1 B_DL_va… Anas s… 2020-07-29 05:46:48 2020-07-29 05:4…       0      0      0  
#>  2 B_DL_va… Anas s… 2020-07-30 04:29:31 2020-07-30 04:2…   81763   1363.    22.7
#>  3 B_DL_va… Anas s… 2020-08-05 05:02:01 2020-08-05 05:0…  520350   8672.   145. 
#>  4 B_DM_va… Ardea   2021-04-05 19:08:33 2021-04-05 19:0…       0      0      0  
#>  5 B_DM_va… Ardea   2021-04-11 19:43:09 2021-04-11 19:4…  520476   8675.   145. 
#>  6 B_DL_va… Castor… 2020-06-19 22:05:55 2020-06-19 22:0…       0      0      0  
#>  7 B_DL_va… Martes… 2020-06-28 22:01:12 2020-06-28 22:0…       0      0      0  
#>  8 B_DL_va… Mustel… 2020-06-19 22:31:51 2020-06-19 22:3…       0      0      0  
#>  9 B_DL_va… Mustel… 2020-06-23 23:33:53 2020-06-23 23:3…  349322   5822.    97.0
#> 10 B_DL_va… Mustel… 2020-06-28 23:33:16 2020-06-28 23:3…  431963   7199.   120. 
#> 11 B_DL_va… Vulpes… 2020-06-26 02:09:25 2020-06-26 02:0…       0      0      0  
#> # … with 3 more variables: delta.time.days <dbl>, Directory <list>,
#> #   FileName <list>, and abbreviated variable names ¹​delta.time.secs,
#> #   ²​delta.time.mins, ³​delta.time.hours

Station names

The column containing the station names can also be defined by the user if the default value, "locationName", is not the correct one. It has to be a valid column of deployments. Here below, locationID is used:

get_record_table(mica, stationCol = "locationID")
#> # A tibble: 17 × 11
#>    Station  Species DateTimeOriginal    Date       Time  delta…¹ delta…² delta…³
#>    <chr>    <chr>   <dttm>              <date>     <chr>   <dbl>   <dbl>   <dbl>
#>  1 2df5259… Anas p… 2020-07-31 04:43:33 2020-07-31 04:4…       0      0      0  
#>  2 2df5259… Anas p… 2020-08-02 05:00:14 2020-08-02 05:0…  173801   2897.    48.3
#>  3 2df5259… Anas p… 2020-08-03 05:09:12 2020-08-03 05:0…   86938   1449.    24.1
#>  4 2df5259… Anas p… 2020-08-04 05:04:09 2020-08-04 05:0…   86097   1435.    23.9
#>  5 2df5259… Anas s… 2020-07-29 05:46:48 2020-07-29 05:4…       0      0      0  
#>  6 2df5259… Anas s… 2020-07-30 04:29:31 2020-07-30 04:2…   81763   1363.    22.7
#>  7 2df5259… Anas s… 2020-08-05 05:02:01 2020-08-05 05:0…  520350   8672.   145. 
#>  8 ce943ce… Ardea   2021-04-05 19:08:33 2021-04-05 19:0…       0      0      0  
#>  9 ce943ce… Ardea   2021-04-11 19:43:09 2021-04-11 19:4…  520476   8675.   145. 
#> 10 ce943ce… Ardea … 2021-03-27 20:38:18 2021-03-27 20:3…       0      0      0  
#> 11 ff1535c… Castor… 2020-06-19 22:05:55 2020-06-19 22:0…       0      0      0  
#> 12 3232bcf… Homo s… 2019-10-23 10:19:44 2019-10-23 10:1…       0      0      0  
#> 13 ff1535c… Martes… 2020-06-28 22:01:12 2020-06-28 22:0…       0      0      0  
#> 14 ff1535c… Mustel… 2020-06-19 22:31:51 2020-06-19 22:3…       0      0      0  
#> 15 ff1535c… Mustel… 2020-06-23 23:33:53 2020-06-23 23:3…  349322   5822.    97.0
#> 16 ff1535c… Mustel… 2020-06-28 23:33:16 2020-06-28 23:3…  431963   7199.   120. 
#> 17 ff1535c… Vulpes… 2020-06-26 02:09:25 2020-06-26 02:0…       0      0      0  
#> # … with 3 more variables: delta.time.days <dbl>, Directory <list>,
#> #   FileName <list>, and abbreviated variable names ¹​delta.time.secs,
#> #   ²​delta.time.mins, ³​delta.time.hours

Remove duplicates

It can happen that “duplicates” occur, e.g. when two distinct observations of the same species are made based on the same sequence of images, e.g. same species but different lifeStage or sex. You can decide what to do with these duplicates by using the argument removeDuplicateRecords: by default it is equalt to TRUE. The duplicates are therefore removed. To not remove them, set removeDuplicateRecords equal to FALSE.

Let’s create an easy example with duplicates based on mica datapackage:

mica_dup <- mica
  mica_dup$observations$sequenceID <- mica_dup$observations$sequenceID[1]
  mica_dup$observations$deploymentID <- mica_dup$observations$deploymentID[1]
  mica_dup$observations$timestamp <- mica_dup$observations$timestamp[1]
  mica_dup$observations$scientificName <- "Anas strepera"

Record table without duplicates:

# equivalent of get_record_table(mica, removeDuplicateRecords = TRUE)
get_record_table(mica_dup)
#> # A tibble: 17 × 11
#>    Station  Species DateTimeOriginal    Date       Time  delta…¹ delta…² delta…³
#>    <chr>    <chr>   <dttm>              <date>     <chr>   <dbl>   <dbl>   <dbl>
#>  1 B_DL_va… Anas p… 2020-07-31 04:43:33 2020-07-31 04:4…       0      0      0  
#>  2 B_DL_va… Anas p… 2020-08-02 05:00:14 2020-08-02 05:0…  173801   2897.    48.3
#>  3 B_DL_va… Anas p… 2020-08-03 05:09:12 2020-08-03 05:0…   86938   1449.    24.1
#>  4 B_DL_va… Anas p… 2020-08-04 05:04:09 2020-08-04 05:0…   86097   1435.    23.9
#>  5 B_DL_va… Anas s… 2020-07-29 05:46:48 2020-07-29 05:4…       0      0      0  
#>  6 B_DL_va… Anas s… 2020-07-30 04:29:31 2020-07-30 04:2…   81763   1363.    22.7
#>  7 B_DL_va… Anas s… 2020-08-05 05:02:01 2020-08-05 05:0…  520350   8672.   145. 
#>  8 B_DM_va… Ardea   2021-04-05 19:08:33 2021-04-05 19:0…       0      0      0  
#>  9 B_DM_va… Ardea   2021-04-11 19:43:09 2021-04-11 19:4…  520476   8675.   145. 
#> 10 B_DM_va… Ardea … 2021-03-27 20:38:18 2021-03-27 20:3…       0      0      0  
#> 11 B_DL_va… Castor… 2020-06-19 22:05:55 2020-06-19 22:0…       0      0      0  
#> 12 Mica Vi… Homo s… 2019-10-23 10:19:44 2019-10-23 10:1…       0      0      0  
#> 13 B_DL_va… Martes… 2020-06-28 22:01:12 2020-06-28 22:0…       0      0      0  
#> 14 B_DL_va… Mustel… 2020-06-19 22:31:51 2020-06-19 22:3…       0      0      0  
#> 15 B_DL_va… Mustel… 2020-06-23 23:33:53 2020-06-23 23:3…  349322   5822.    97.0
#> 16 B_DL_va… Mustel… 2020-06-28 23:33:16 2020-06-28 23:3…  431963   7199.   120. 
#> 17 B_DL_va… Vulpes… 2020-06-26 02:09:25 2020-06-26 02:0…       0      0      0  
#> # … with 3 more variables: delta.time.days <dbl>, Directory <list>,
#> #   FileName <list>, and abbreviated variable names ¹​delta.time.secs,
#> #   ²​delta.time.mins, ³​delta.time.hours

Record table with duplicates:

get_record_table(mica_dup, removeDuplicateRecords = FALSE)
#> # A tibble: 17 × 11
#>    Station  Species DateTimeOriginal    Date       Time  delta…¹ delta…² delta…³
#>    <chr>    <chr>   <dttm>              <date>     <chr>   <dbl>   <dbl>   <dbl>
#>  1 B_DL_va… Anas p… 2020-07-31 04:43:33 2020-07-31 04:4…       0      0      0  
#>  2 B_DL_va… Anas p… 2020-08-02 05:00:14 2020-08-02 05:0…  173801   2897.    48.3
#>  3 B_DL_va… Anas p… 2020-08-03 05:09:12 2020-08-03 05:0…   86938   1449.    24.1
#>  4 B_DL_va… Anas p… 2020-08-04 05:04:09 2020-08-04 05:0…   86097   1435.    23.9
#>  5 B_DL_va… Anas s… 2020-07-29 05:46:48 2020-07-29 05:4…       0      0      0  
#>  6 B_DL_va… Anas s… 2020-07-30 04:29:31 2020-07-30 04:2…   81763   1363.    22.7
#>  7 B_DL_va… Anas s… 2020-08-05 05:02:01 2020-08-05 05:0…  520350   8672.   145. 
#>  8 B_DM_va… Ardea   2021-04-05 19:08:33 2021-04-05 19:0…       0      0      0  
#>  9 B_DM_va… Ardea   2021-04-11 19:43:09 2021-04-11 19:4…  520476   8675.   145. 
#> 10 B_DM_va… Ardea … 2021-03-27 20:38:18 2021-03-27 20:3…       0      0      0  
#> 11 B_DL_va… Castor… 2020-06-19 22:05:55 2020-06-19 22:0…       0      0      0  
#> 12 Mica Vi… Homo s… 2019-10-23 10:19:44 2019-10-23 10:1…       0      0      0  
#> 13 B_DL_va… Martes… 2020-06-28 22:01:12 2020-06-28 22:0…       0      0      0  
#> 14 B_DL_va… Mustel… 2020-06-19 22:31:51 2020-06-19 22:3…       0      0      0  
#> 15 B_DL_va… Mustel… 2020-06-23 23:33:53 2020-06-23 23:3…  349322   5822.    97.0
#> 16 B_DL_va… Mustel… 2020-06-28 23:33:16 2020-06-28 23:3…  431963   7199.   120. 
#> 17 B_DL_va… Vulpes… 2020-06-26 02:09:25 2020-06-26 02:0…       0      0      0  
#> # … with 3 more variables: delta.time.days <dbl>, Directory <list>,
#> #   FileName <list>, and abbreviated variable names ¹​delta.time.secs,
#> #   ²​delta.time.mins, ³​delta.time.hours

Use filter predicates

As for visualization and all other functions, you can select a subset of deployments by using filter predicates. E.g. to get the record table of observations for the deployments with latitude equal or higher than 51.18:

get_record_table(mica, pred_gt("latitude", 51.18))
#> df %>% dplyr::filter((latitude > 51.18))
#> # A tibble: 13 × 11
#>    Station  Species DateTimeOriginal    Date       Time  delta…¹ delta…² delta…³
#>    <chr>    <chr>   <dttm>              <date>     <chr>   <dbl>   <dbl>   <dbl>
#>  1 B_DL_va… Anas p… 2020-07-31 04:43:33 2020-07-31 04:4…       0      0      0  
#>  2 B_DL_va… Anas p… 2020-08-02 05:00:14 2020-08-02 05:0…  173801   2897.    48.3
#>  3 B_DL_va… Anas p… 2020-08-03 05:09:12 2020-08-03 05:0…   86938   1449.    24.1
#>  4 B_DL_va… Anas p… 2020-08-04 05:04:09 2020-08-04 05:0…   86097   1435.    23.9
#>  5 B_DL_va… Anas s… 2020-07-29 05:46:48 2020-07-29 05:4…       0      0      0  
#>  6 B_DL_va… Anas s… 2020-07-30 04:29:31 2020-07-30 04:2…   81763   1363.    22.7
#>  7 B_DL_va… Anas s… 2020-08-05 05:02:01 2020-08-05 05:0…  520350   8672.   145. 
#>  8 B_DL_va… Castor… 2020-06-19 22:05:55 2020-06-19 22:0…       0      0      0  
#>  9 B_DL_va… Martes… 2020-06-28 22:01:12 2020-06-28 22:0…       0      0      0  
#> 10 B_DL_va… Mustel… 2020-06-19 22:31:51 2020-06-19 22:3…       0      0      0  
#> 11 B_DL_va… Mustel… 2020-06-23 23:33:53 2020-06-23 23:3…  349322   5822.    97.0
#> 12 B_DL_va… Mustel… 2020-06-28 23:33:16 2020-06-28 23:3…  431963   7199.   120. 
#> 13 B_DL_va… Vulpes… 2020-06-26 02:09:25 2020-06-26 02:0…       0      0      0  
#> # … with 3 more variables: delta.time.days <dbl>, Directory <list>,
#> #   FileName <list>, and abbreviated variable names ¹​delta.time.secs,
#> #   ²​delta.time.mins, ³​delta.time.hours

Other arguments needed?

Are there other arguments of camtrapR’s function recordTable() you think should be relevant to add to get_camera_record(), please let us know by posting an issue!