Some things to consider before making kernel density estimations.
This post is to exemplify some considerations when calculating kernel density analyses.
Before start calculating kernel density analyses, its useful to consider some sources of error that might change your results.
For the exercises, test data is from masked boobies.
To access
the data you have to install the package sula:
devtools::install_github(“MiriamLL/sula”)
#devtools::install_github("MiriamLL/sula")
library(sula)
GPS_raw<-(GPS_raw)
To manipulate the data we will use functions from the package tidyverse
For spatial manipulations we will use functions from the packages sp and sf
For creating the polygons of kernel density we will use the package adehabitathr
library(adehabitatHR)
Some individuals might drive kernel density calculations in one or other direction as effect of different number of recordings (or days recorded) per individual.
To illustrate this, lets see the calculations using together one individual sampled for 1 day and other for 5 days
Unpaired<-rbind(ID_1day,ID_5days)
Transform to spatial object.
Unpaired<-as.data.frame(Unpaired)
coordinates(Unpaired) <- c("Longitude", "Latitude")
class(Unpaired)
[1] "SpatialPointsDataFrame"
attr(,"package")
[1] "sp"
Calculate kernelUD.
UnpairedUD<-kernelUD(Unpaired[,3],h='href')
Obtain polygons.
UnpairedUD95 <- getverticeshr(UnpairedUD, percent = 95, unout = c("m2"))
UnpairedUD50 <- getverticeshr(UnpairedUD, percent = 50, unout = c("m2"))
Here you can check on you polygons visually.
To compare, lets now see the kernel density calculated with these same individuals but recorded at similar number of days (3 days)
Paired<-rbind(ID_01,ID_03)
Transform to spatial object.
Paired<-as.data.frame(Paired)
coordinates(Paired) <- c("Longitude", "Latitude")
class(Paired)
[1] "SpatialPointsDataFrame"
attr(,"package")
[1] "sp"
Calculate kernelUD.
PairedUD<-kernelUD(Paired[,3],h='href')
Obtain polygons.
PairedUD95 <- getverticeshr(PairedUD, percent = 95, unout = c("m2"))
PairedUD50 <- getverticeshr(PairedUD, percent = 50, unout = c("m2"))
Here you can check on you polygons visually.
As you can see the resulting areas would be different.
To solve this problem, you might want to make sure to have tracking data of similar number of days or recordings.
Do you have similar recordings in time?
If some devices have gaps, or record at different intervals, you might underestimate or overestimate specific areas.
For this example, lets see one individuals
Using the column of hours, lets extract all the recordings after 5 pm.
GPS01$Hour <- as.numeric(substr(GPS01$TimeGMT, 1, 2))
Gaps<-GPS01 %>%
filter(Hour <= 17)
Transform to spatial object.
Gaps<-as.data.frame(Gaps)
coordinates(Gaps) <- c("Longitude", "Latitude")
Calculate kernelUD.
GapsUD<-kernelUD(Gaps[,3],h='href')
Obtain polygons.
GapsUD95 <- getverticeshr(GapsUD, percent = 95, unout = c("m2"))
GapsUD50 <- getverticeshr(GapsUD, percent = 50, unout = c("m2"))
Here you can check on you polygons visually.
In contrast, the kernel density calculations without gaps would give different results.
Transform to spatial object.
Complete<-as.data.frame(Complete)
coordinates(Complete) <- c("Longitude", "Latitude")
Calculate kernelUD.
CompleteUD<-kernelUD(Complete[,3],h='href')
Obtain polygons.
CompleteUD95 <- getverticeshr(CompleteUD, percent = 95, unout = c("m2"))
CompleteUD50 <- getverticeshr(CompleteUD, percent = 50, unout = c("m2"))
Here you can check on you polygons visually.
To solve the problem with gaps, you can interpolate the data to fill the gaps and have similar intervals. However, caution should be taken if you have large gaps, it would create a line.
Do you want to know the general areas that the animal used or just where it was feeding?
It depends on your question, but if you are interested in specific behaviours, for example feeding areas, the kernel density analyses might be bring very different results than when using all movement data.
Here, we are using only areas where the animal was foraging.
Load data
GPS_raw<-as.data.frame(GPS_raw)
GPS01<-subset(GPS_raw,GPS_raw$IDs=='GPS01')
Use an specific period
GPS_bc<-recortar_periodo(GPS_data=GPS01,
inicio='02/11/2017 18:10:00',
final='05/11/2017 14:10:00',
dia_col='DateGMT',
hora_col='TimeGMT',
formato="%d/%m/%Y %H:%M:%S")
ES: El track original contenia 1038 filas y el track editado contiene 986 filas
EN: The original track had 1038 rows, and the edited track has 986
Convert to the correct format
GPS_bc$tStamp<-paste(GPS_bc$DateGMT,GPS_bc$TimeGMT)
GPS_bc$tStamp <- as.POSIXct(strptime(GPS_bc$tStamp,"%d/%m/%Y %H:%M:%S"),"GMT")
GPS_bc$lon<- as.numeric(GPS_bc$Longitude)
GPS_bc$lat<- as.numeric(GPS_bc$Latitude)
GPS_bc$id <- as.factor(GPS_bc$IDs)
Keep only the important columns
Load the package
library(EMbC)
Run the function
BC_clustering<-EMbC::stbc(GPS_bc[2:4],info=-1)
[1] 0 -0.0000e+00 4 986
[1] ... Stable clustering
Add the behavioral classifications
GPS_bc$Behaviours<-(BC_clustering@A)
Rename it so you can understand what each behaviour means
Filter to keep only foraging
Transform to spatial object
Foraging<-as.data.frame(Foraging)
coordinates(Foraging) <- c("lon", "lat")
Calculate kernelUD.
Note Here the href is of 0.0048 which is giving the error of subscript out of bounds Lets then better calculate using other h value
#ForagingUD<-kernelUD(Foraging[,3],h='href')
#ForagingUD95 <- getverticeshr(ForagingUD, percent = 95, unout = c("m2"))
The new h value is of 0.01
ForagingUD<-kernelUD(Foraging[,3],h=0.009)
ForagingUD
********** Utilization distribution of several Animals ************
Type: probability density
Smoothing parameter estimated with a specified smoothing parameter
This object is a list with one component per animal.
Each component is an object of class estUD
See estUD-class for more information
Obtain polygons.
ForagingUD95 <- getverticeshr(ForagingUD, percent = 95, unout = c("m2"))
ForagingUD50 <- getverticeshr(ForagingUD, percent = 50, unout = c("m2"))
Here you can check on you polygons visually.
Here, we are using all the areas.
Behas<-as.data.frame(GPS_bc)
coordinates(Behas) <- c("lon", "lat")
Calculate kernelUD.
BehasUD<-kernelUD(Behas,h='href')
BehasUD
********** Utilization distribution of an Animal ************
Type: probability density
Smoothing parameter estimated with a href parameter
This object inherits from the class SpatialPixelsDataFrame.
See estUD-class for more information
Obtain polygons.
BehasUD95 <- getverticeshr(BehasUD, percent = 95, unout = c("m2"))
BehasUD50 <- getverticeshr(BehasUD, percent = 50, unout = c("m2"))
Here you can check on you polygons visually.
If you want to classify the behaviour, please check the post on EmBC