PatTrEnvDat Week 5

Author

Jannis Bolzern

Task 1: Write own functions

Function to calculate BMI

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

Function to convert Celsius to Fahrenheit

celsius_to_fahrenheit <- function(celsius) {
  fahrenheit <- (celsius * 9/5) + 32
  return(fahrenheit)
}

Function to calculate Euclidean distance between two points

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

Task 2: Prepare Analysis

library(tidyverse)
library(dplyr)
library(lubridate)

Import dataset

wildschwein <- read_delim("wildschwein_BE_2056.csv")

Convert DatetimeUTC to POSIXct

wildschwein$DatetimeUTC <- as.POSIXct(wildschwein$DatetimeUTC, tz = "UTC")

Filter for Rosa and Sabi between 01.04.2015 - 15.04.2015

wildschwein_filter <- wildschwein %>%
  filter(TierName %in% c("Rosa", "Sabi"),
         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

Round datetime to nearest 15 minutes

wildschwein_filter <- wildschwein_filter %>%
  mutate(DatetimeRound = round_date(DatetimeUTC, "15 minutes"))

Task 4: Measuring distance at concurrent locations

Split into separate dataframes for each animal

rosa <- wildschwein_filter %>% filter(TierName == "Rosa")
sabi <- wildschwein_filter %>% filter(TierName == "Sabi")

Join the datasets by the rounded datetime

joined_data <- inner_join(rosa, sabi, by = "DatetimeRound", suffix = c("_rosa", "_sabi"))

Calculate Euclidean distance between concurrent observations

joined_data <- joined_data %>%
  mutate(distance = euclidean_distance(E_rosa, N_rosa, E_sabi, N_sabi))

Add a column indicating if it’s a meet (distance < 100 meters)

joined_data <- joined_data %>%
  mutate(meet = distance < 100)

Task 5: Visualize data

library(ggplot2)

Filter for meets only

meets_data <- joined_data %>% filter(meet == TRUE)

Create the plot

ggplot() +
  # Plot Rosa's trajectory
  geom_path(data = rosa, aes(x = E, y = N), color = "blue", alpha = 0.5) +
  # Plot Sabi's trajectory
  geom_path(data = sabi, aes(x = E, y = N), color = "red", alpha = 0.5) +
  # Plot the meet points
  geom_point(data = meets_data, aes(x = E_rosa, y = N_rosa), color = "purple", size = 3) +
  # Add labels and title
  labs(title = "Wild Boar Trajectories and Meet Points",
       x = "Easting", y = "Northing",
       subtitle = "Blue: Rosa, Red: Sabi, Purple: Meet Points") +
  coord_cartesian(xlim = c(min(c(rosa$E, sabi$E)) - 100, max(c(rosa$E, sabi$E)) + 100),
                  ylim = c(min(c(rosa$N, sabi$N)) - 100, max(c(rosa$N, sabi$N)) + 100)) +
  theme_minimal()

Task 6: Visualize data as timecube with plotly

library(plotly)

Prepare data for plotly

plot_data <- wildschwein_filter %>% 
  filter(TierName %in% c("Rosa", "Sabi"))

meet_data <- joined_data %>% 
  filter(meet) %>%
  mutate(MidX = (E_rosa + E_sabi)/2,
         MidY = (N_rosa + N_sabi)/2)

Create the 3D plot

plot_ly() %>%
  add_paths(data = filter(plot_data, TierName == "Rosa"),
            x = ~E, y = ~N, z = ~DatetimeUTC,
            color = I("blue"), name = "Rosa") %>%
  add_paths(data = filter(plot_data, TierName == "Sabi"),
            x = ~E, y = ~N, z = ~DatetimeUTC,
            color = I("red"), name = "Sabi") %>%
  add_markers(data = meet_data,
              x = ~MidX, y = ~MidY, z = ~DatetimeRound,
              color = I("purple"), name = "Meets") %>%
  layout(scene = list(
         zaxis = list(type = "date",
                      tickformat = "%H:%M<br>%b %d",
                      dtick = 86400000)))