E5

library("readr")
library("sf")
Linking to GEOS 3.12.2, GDAL 3.9.3, PROJ 9.4.1; sf_use_s2() is TRUE
library("dplyr")

Attache Paket: 'dplyr'
Die folgenden Objekte sind maskiert von 'package:stats':

    filter, lag
Die folgenden Objekte sind maskiert von 'package:base':

    intersect, setdiff, setequal, union
library(ggplot2)
library(SimilarityMeasures)
library(tidyr)
library(lubridate)

Attache Paket: 'lubridate'
Die folgenden Objekte sind maskiert von 'package:base':

    date, intersect, setdiff, union

Task 1: Write your own functions

Create the following two functions:

A function which calculates a persons BMI based on their height and weight (Equation 21.1) A function which converts degrees Celcius to Farenheight (Equation 21.2) A function which calculates the (Euclidean) distance between two sets of coordinates

BMI

bmi <- function(weight_kg, height_m) {
  bmi_output <- weight_kg/height_m^2
  return(bmi_output)
}

bmi(84, 1.9)
[1] 23.2687

Fahrenheit

celcius_to_fahrenheit <- function(celsius){celsius*9/5 + 32}

celcius_to_fahrenheit(18)
[1] 64.4

Euclidean Distance

euclidean_dist <- function(x1, y1, x2, y2){
  sqrt((x2 - x1)^2 + (y2 - y1)^2)
}

euclidean_dist(0, 0, 1, 1)
[1] 1.414214

Task 2: Prepare Analysis

In the next tasks we will look for “meet” patterns in our wild boar data. To simplify this, we will only use a subset of our wild boar data: The individuals Rosa and Sabi for the timespan 01.04.2015 - 15.04.2015. Use the dataset wildschwein_BE_2056.csv (on moodle). Import the csv as a data.frame and filter it with the aforementioned criteria. You do not need to convert the data.frame to an sf object.

wildschwein <- read_delim("data/wildschwein_BE_2056.csv", ",") |> 
      filter(
      TierName == "Sabi" | TierName == "Rosa", 
      DatetimeUTC >= "2015-04-01" & DatetimeUTC < "2015-04-15"
      )
Rows: 51246 Columns: 6
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr  (2): TierID, TierName
dbl  (3): CollarID, E, N
dttm (1): DatetimeUTC

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

Task 3: Create Join Key

Have a look at your dataset. You will notice that samples are taken at every full hour, quarter past, half past and quarter to. The sampling time is usually off by a couple of seconds.

To compare Rosa and Sabi’s locations, we first need to match the two animals temporally. For that we can use a join, but need identical time stamps to serve as a join key. We therefore need to slightly adjust our time stamps to a common, concurrent interval.

The task is therfore to round the minutes of DatetimeUTC to a multiple of 15 (00, 15, 30,45) and store the values in a new column1. You can use the lubridate function round_date() for this. See the examples here to see how this goes.

wildschwein <- wildschwein |> 
  mutate(
    DatetimeUTC_c = round_date(DatetimeUTC, "15 mins")
  )

Task 4: Measuring distance at concurrent locations

To measure the distance between concurrent locations, we need to follow the following steps.

  1. Split the wildschwein_filter object into one data.frame per animal
  2. Join these datasets by the new Datetime column created in the last task. The joined observations are temporally close.
  3. In the joined dataset, calculate Euclidean distances between concurrent observations and store the values in a new column
  4. Use a reasonable threshold on distance to determine if the animals are also spatially close enough to constitute a meet (we use 100 meters). Store this Boolean information (TRUE/FALSE) in a new column
# 1. split
rosa <- wildschwein |> 
  filter(
    TierName == "Rosa"
  )

sabi <- wildschwein |> 
  filter(
    TierName == "Sabi"
  )

# 2. Join
both <- inner_join(rosa, sabi, by = "DatetimeUTC_c", suffix = c("_rosa", "_sabi"))

# 3. Euclidean Distance &  4. Distance Threshold
both <- both |> 
  mutate(
    euc_dist = sqrt((N_sabi - N_rosa)^2 + (E_sabi - E_rosa)^2),
    close = euc_dist < 100
  )

zusammen <- both |> 
  filter(
    close == T
  )

hist(both$euc_dist, breaks = 20)

Task 5: Visualize data

Now, visualize the meets spatially in a way that you think reasonable. For example in the plot as shows below

comb <- bind_rows(rosa, sabi)

zusammen_long <- zusammen |> 
  select(c(TierName_rosa, TierName_sabi, E_rosa, N_rosa, E_sabi, N_sabi, DatetimeUTC_c)) |>
  pivot_longer(cols = c(TierName_rosa, TierName_sabi,
             E_rosa, N_rosa,
             E_sabi, N_sabi),
    names_to = c(".value", "tier"),
    names_sep = "_") |>
  select(TierName, E, N, DatetimeUTC_c)

ggplot() +
  geom_point(data = comb, aes(x = E, y = N, color = TierName), alpha = 0.3, size = 2) +
  geom_point(data = zusammen_long, aes(x = E, y = N, fill = TierName), shape = 21, size = 3, stroke = 1) +
  scale_color_manual(name = "Regular Locations",
                     values = c("Rosa" = "red", "Sabi" = "blue")) +
  scale_fill_manual(name = "Meets",
                    values = c("Rosa" = "red", "Sabi" = "blue")) +
  labs(x = "E", y = "N")