knitr::opts_chunk$set( collapse = TRUE, comment = "#>" )
library(trekR) library(lubridate) library(dplyr) library(tibble)
The example shown below is one of many ways the data could be processed. The important components required is a list
object containing home range kernels for each interval that is created for at least one individual.
For example, for a single individual if I wanted to break a one month period into 10-day intervals I would get a total of three 10-day intervals. These intervals should be in a list
object, and each element within the list
should represent a single interval.
The selected periods to be divided into intervals should be chosen so that they fall between migratory trips and don't overlap them. For example if individuals typically begin their migratory trip in spring and fall, the selected periods should not overlap spring and fall, and should be during the winter and summer seasons.
We created 10-day intervals for deer in the January and July. We first created a start
column using the floor_Date()
function to obtain the 10-day extents within the months. We included the 31st day (if a month had 31 days) in the third 10-day interval to prevent the creation of a 4th 10-day interval with only a single day in it.
jan <- deer %>% # Creates a start column assigning the first day in the 10-day interval in which # the date falls under (e.g., 01-03-2021 would be in the first 10-day interval # so the `floor_date` assigned to it would be 01-01-2021) mutate(start = floor_date(date, "10 days")) %>% # For any months that has 31 days, the 31st day would normally be assigned its # own interval. The code below takes the 31st day and joins it with the # previous interval. group_by(ID) %>% mutate(start = if_else(day(start) == 31, start - days(10), start)) %>% group_by(start, .add = TRUE) %>% filter(month == "1") %>% group_split()
july <- deer %>% # Creates a start column assigning the first day in the 10-day interval in which # the date falls under (e.g., 01-03-2021 would be in the first 10-day interval # so the `floor_date` assigned to it would be 01-01-2021) mutate(start = floor_date(date, "10 days")) %>% # For any months that has 31 days, the 31st day would normally be assigned its # own interval. The code below takes the 31st day and joins it with the # previous interval. group_by(ID) %>% mutate(start = if_else(day(start) == 31, start - days(10), start)) %>% group_by(start, .add = TRUE) %>% filter(month == "7") %>% group_split()
Elements in the list for one individual in January:
head(jan[1:3])
Before we estimate LoCoH home range for each of these 10-day intervals, we first create objects of class track_xyt
using make_track()
from the amt
package. This function creates a track
using the utm_x
and utm_y
columns from jan
and july
. lapply()
allows us to apply the specified function across a list
object (e.g., jan
and july
)
track_list_sum <- lapply(july, function(x) { amt::make_track(tbl = x, .x = utm_x, .y = utm_y, .t = date, uid = ID, # lat/long: 4326 (lat/long, WGS84 datum). # utm: crs = sp::CRS("+init=epsg:32612")) crs = 32612) }) track_list_win <- lapply(jan, function(x) { amt::make_track(tbl = x, .x = utm_x, .y = utm_y, .t = date, uid = ID, crs = 32612) })
Using the track
created for the jan
and july
, we estimate type "a" LoCoH home range using hr_locoh()
from the amt
package. If you would like to learn more about the arguments of this function please refer to ?amt::hr_locoh
for more details.
sum_locoh <- lapply(track_list_sum, function(tracks){ # Calculate LoCoH a* dmat <- dist(tracks[, c("x_", "y_")]) a <- max(dmat) # Fit LoCoH locoh <- try(amt::hr_locoh( x = tracks, levels = seq(0.1, 1, by = 0.1), keep.data = TRUE, n = a, type = "a", rand_buffer = 1e-05 )) }) win_locoh <- lapply(track_list_win, function(tracks){ # Calculate LoCoH a* dmat <- dist(tracks[, c("x_", "y_")]) a <- max(dmat) # Fit LoCoH locoh <- try(amt::hr_locoh( x = tracks, levels = seq(0.1, 1, by = 0.1), keep.data = TRUE, n = a, type = "a", rand_buffer = 1e-05 )) })
We then created isopleths from the LoCoH home range estimates using hr_isopleths()
from the amt
package.
sum_iso <- lapply(sum_locoh, function(x){ amt::hr_isopleths(x) }) win_iso <- lapply(win_locoh, function(x){ amt::hr_isopleths(x) })
After creating isopleths for each of the intervals, we have to rasterize them. Similar to the the previous functions, we use lapply()
to apply our function across our list
object. We first select the resolution for that we want for our rasters (res
). We then create a template raster with a resolution of res
(keep in mind that the speed the isopleths are rasterize()
will be dependent on the specified resolution, with time of processing increasing with smaller resolutions). The projection of the template raster will match that of the specified isopleth.
After creating rasters for each interval, we then subtract all the isopleth values from 1, then normalize them.
res <- 250 sum_raster <- lapply(sum_iso, function(iso){ # Creates template raster template_raster <- raster::raster(iso, resolution = res, vals = 0, crs = sp::CRS(sf::st_crs(iso)[[2]]) ) # Rasterizes the isopleth raster_locoh <- raster::rasterize(iso, template_raster, field = "level", fun = "first" ) # Now you want to subtract all the isopleth values from 1 raster::values(raster_locoh) <- 1 - raster::values(raster_locoh) # Now normalize x <- raster_locoh / raster::cellStats(raster_locoh, sum) }) win_raster <- lapply(win_iso, function(iso){ # Creates template raster template_raster <- raster::raster(iso, resolution = res, vals = 0, crs = sp::CRS(sf::st_crs(iso)[[2]]) ) # Rasterizes the isopleth raster_locoh <- raster::rasterize(iso, template_raster, field = "level", fun = "first" ) # Now you want to subtract all the isopleth values from 1 raster::values(raster_locoh) <- 1 - raster::values(raster_locoh) # Now normalize x <- raster_locoh / raster::cellStats(raster_locoh, sum) }) names(win_raster) <- sapply(jan, function(x) paste(x$ID[1], x$year[1], sep = '_')) names(sum_raster) <- sapply(july, function(x) paste(x$ID[1], x$year[1], sep = '_'))
We attach attributes to our list of rasters to allow for more flexibility in working with our lists of rasters.
# Add an attribute to hold the attributes of each list element attributes(win_raster) <- data.frame(id = sapply(jan, function(x) paste(x$ID[1])), interval_start_date = sapply(jan, function(x) paste(x$start[1])), year = paste0(sapply(jan, function(x) paste(x$year[1]))) ) # Check the attributes attributes(win_raster) # Add an attribute "tab" to hold the attributes of each list element attributes(sum_raster) <- data.frame(id = sapply(july, function(x) paste(x$ID[1])), interval_start_date = sapply(july, function(x) paste(x$start[1])), year = paste0(sapply(july, function(x) paste(x$year[1]))) ) # Check the attributes attributes(sum_raster)
The data set up above have specifically focused on setting up the data for calculating EMDs in geographical space. The code below demonstrates how you can set up the data to calculate the EMDs in environmental space.
We first import the environmental covariate file (e.g., DEM layer), then we re-project the extent from latitude and longitude to UTMs to match those of the home range rasters.
#Load raster UtahDEM <- raster::raster(system.file("extdata", "Utah_DEM.tif", package = "trekR")) out_proj <- "+proj=utm +zone=12 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0" UtahDEM@extent <- raster::extent(raster::projectExtent(UtahDEM, out_proj))
The env_raster_stack()
function takes the environmental covariate raster and resamples it to the home range rasters. It then takes the resampled rasters and the home range rasters and constructs a object with class RasterStack
. The steps following the creation of these RasterStacks
is the steps under "Earth Mover's Distance", where the RasterLayers
objects (i.e., sum_raster
and win_raster
) are replaced with the RasterStack
objects (i.e., sum_rst
and win_rst
).
sum_rst <- env_raster_stack(UtahDEM, sum_raster) win_rst <- env_raster_stack(UtahDEM, win_raster)
For environmental covariates that vary across time (e.g., temperature, snow depth, foraging resources, precipitation, etc.), we first assign the file names of which the covariates are housed to list_names
. In our example, we use Rangeland Analysis Platform (RAP) data in 2013 and 2014 that can be an indicator of forage resources on the landscape.
list_names <- list.files(path=system.file("extdata", package = "trekR"), pattern=c("RAP","*.tif"), all.files= FALSE, full.names = TRUE) basename(list_names)
We then read in those files into R as RasterLayer
objects. For each of those list
elements in env_lists
we assign the path names for each of those files. Using the assigned names, we created attributes(metadata) for our list with a year
column. The year
column may change depending on the temporal scale of your environmental covariate. For example, if we had environmental covariates that changed daily, we can first aggregate the daily covariates based the intervals. Instead of using year
, we would then use the start date of the intervals.
# Rasterize the environmental covariates env_list <- lapply(list_names, raster::raster) names(env_list) <- sapply(list_names, function(x) paste(x)) # Uses the name of the environemntal covariate file to assign attributes attributes(env_list) <- data.frame(year = trimws(basename(names(env_list)), whitespace = "_.*")) attributes(env_list)
We use env_raster_stack
with the addition of the attribute
argument to stack environmental covariate layers with our home range rasters. The input for the attribute
argument should be a attribute component that is the same in both of the list
objects (i.e., env_list and sum_raster/win_raster) with the same unique values. For example, both env_list
and sum_raster
/win_raster
have a attribute component labelled year
and both have the same unique values (e.g., 2013 and 2014).
NOTE: Currently this feature assumes that only environmental layers relevant to sum_raster
or win_raster
are being used and are in the same folder(i.e., excluding any that are not present in sum_raster
and/or win_raster
.)
sum_rst_temporal <- env_raster_stack(env_list, sum_raster, attribute = "year") win_rst_temporal <- env_raster_stack(env_list, win_raster, attribute = "year")
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.