Ex5

Author

Sven Imdorf

Published

March 19, 2025

Task 1: Write your own 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 (see Equation 21.3)

 # BMI (Equation 21.1)
calc_bmi <- function(weight_kg, height_m) {
  bmi <- weight_kg / (height_m^2)
  return(bmi)
}

# Fahrenheit (Equation 21.2)
cels_to_fahr <- function(celsius) {
  fahrenheit <- (celsius * 9/5) + 32
  return(fahrenheit)
}

# Function to calculate Euclidean distance between two coordinate points (Equation 21.3)
euc_dist <- function(x1, y1, x2, y2) {
  distance <- sqrt((x2 - x1)^2 + (y2 - y1)^2)
  return(distance)
}

Task 2: Prepare Analysis

Use the dataset wildschwein_BE_2056.csv (on moodle). Import the csv as a data.frame and filter it with the following criteria:

  • individuals Rosa and Sabi for the timespan 01.04.2015 - 15.04.2015
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
library("tidyr")
library("readr")


wildschwein_BE <- read_delim("../data/wildschwein_BE_2056.csv", delim=",")
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.
wildschw_filter <- wildschwein_BE |> 
filter(TierName %in% c("Sabi", "Rosa") &
  DatetimeUTC >= as.POSIXct("2015-04-01 00:00:00", tz="UTC") &
  DatetimeUTC <= as.POSIXct("2015-04-15 23:59:59", tz="UTC"))

Task 3: Create Join Key

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. Thererfore, 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.

library("lubridate")

Attaching package: 'lubridate'
The following objects are masked from 'package:base':

    date, intersect, setdiff, union
wildschw_rounded <- wildschw_filter %>%
  mutate(RoundedDatetime = round_date(DatetimeUTC, "15 minutes"))

Task 4: Measuring distance at concurrent locations

  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

# Split the data
wildschw_rosa <- wildschw_rounded %>% filter(TierName == "Rosa")
wildschw_sabi <- wildschw_rounded %>% filter(TierName == "Sabi")

# Join the two datasets by  RoundedDatetime 
wildschw_join <- inner_join(wildschw_rosa, wildschw_sabi, by = "RoundedDatetime", suffix = c("_Rosa", "_Sabi"))

# Calculate Euclidean distances
euc_dist <- wildschw_join %>%
  mutate(
    distance = sqrt((E_Rosa - E_Sabi)^2 + (N_Rosa - N_Sabi)^2),
    meet = distance <= 100  # TRUE if the distance is less than or equal to 100 meters
  )

Task 5: Visualize data

library(ggplot2)

# Filter the joined dataset for only the meets (distance <= 100 meters)
meets_data <- euc_dist %>% filter(meet == TRUE)

# Create the plot
ggplot() +
  # Plot Rosa
  geom_point(data = wildschw_rosa, aes(x = E, y = N), color = "blue", alpha = 0.5) +
  # Plot Sabi
  geom_point(data = wildschw_sabi, aes(x = E, y = N), color = "red", alpha = 0.5) +
  # Highlight the meets
  geom_point(data = meets_data, aes(x = E_Rosa, y = N_Rosa), color = "black", shape = 1, size = 2) +
  geom_point(data = meets_data, aes(x = E_Sabi, y = N_Sabi), color = "black", shape = 1, size = 2) +
  # Set the x and y axis limits
  xlim(min(c(wildschw_rosa$E, wildschw_sabi$E)) - 100, max(c(wildschw_rosa$E, wildschw_sabi$E)) + 100) +
  ylim(min(c(wildschw_rosa$N, wildschw_sabi$N)) - 100, max(c(wildschw_rosa$N, wildschw_sabi$N)) + 100) +
  # Add labels and title
  labs(x = "East (E)", y = "North (N)", title = "Meets Between Rosa and Sabi") +
  theme_minimal()