wee5_tasksandinputs

# install.packages("pacman")
library("pacman")

p_install("dplyr", force = FALSE)
Package is already on your system.
p_install("ggplot2", force = FALSE)
Package is already on your system.
p_install("readr", force = FALSE)
Package is already on your system.
p_install("tidyr", force = FALSE)
Package is already on your system.
p_install("sf", force = FALSE)
Package is already on your system.
p_install("terra", force = FALSE)
Package is already on your system.
p_install("tmap", force = FALSE)
Package is already on your system.
p_install("zoo", force = FALSE)
Package is already on your system.
p_install("units", force = FALSE)
Package is already on your system.
p_install("plotly", force = FALSE)
Package is already on your system.
p_install("patchwork", force = FALSE)
Package is already on your system.
library("ggplot2")
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("readr")
library("sf")
Linking to GEOS 3.13.0, GDAL 3.10.1, PROJ 9.5.1; sf_use_s2() is TRUE
library("readr")
library("sf")
library(lubridate)

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

    date, intersect, setdiff, union
# install.packages("SimilarityMeasures")
library("SimilarityMeasures")

Task 1: Write your own functions

BMI <- function(weight, height){
  weight / ((height)^2)
}

BMI(100,2)
[1] 25
celcius_to_farenheight <- function(celcius){celcius * 9/5 +32}
celcius_to_farenheight(30)
[1] 86
euclidean_distance <- function(x1, y1, x2, y2){
  sqrt((x2 - x1)^2 + (y2-y1)^2)
}

Task 2: Prepare Analysis

wildschwein <- read.delim("wildschwein_BE_2056.csv", sep = ",")

wildschwein <- wildschwein |>
  filter(
    TierName %in% c("Rosa", "Sabi"),  # Korrekte Schreibweise für mehrere Werte
    DatetimeUTC >= "2015-04-01", 
    DatetimeUTC < "2015-04-15"
  )

str(wildschwein)
'data.frame':   2688 obs. of  6 variables:
 $ TierID     : chr  "002A" "002A" "002A" "002A" ...
 $ TierName   : chr  "Sabi" "Sabi" "Sabi" "Sabi" ...
 $ CollarID   : int  12275 12275 12275 12275 12275 12275 12275 12275 12275 12275 ...
 $ DatetimeUTC: chr  "2015-04-01T00:00:11Z" "2015-04-01T00:15:22Z" "2015-04-01T00:30:11Z" "2015-04-01T00:45:16Z" ...
 $ E          : num  2570372 2570309 2570326 2570315 2570323 ...
 $ N          : num  1205313 1205262 1205248 1205242 1205237 ...

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.

library(dplyr)
library(lubridate)

wildschwein <- wildschwein %>%
  mutate(
    DatetimeUTC = ymd_hms(DatetimeUTC),  # Convert to POSIXct format
    DatetimeRound = round_date(DatetimeUTC, unit = "15 minutes")  # Round to nearest 15 min
  )

# print(head(wildschwein))

Task 4: Measuring distance at concurrent locations To measure the distance between concurrent locations, we need to follow the following steps.

Split the wildschwein_filter object into one data.frame per animal
Join2 these datasets by the new Datetime column created in the last task. The joined observations are temporally close.
In the joined dataset, calculate Euclidean distances between concurrent observations and store the values in a new column
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
# Step 1.Split the wildschwein_filter dataset by animal
wildschwein_rosa <- wildschwein %>%
  filter(TierName == "Rosa")

wildschwein_sabi <- wildschwein %>%
  filter(TierName == "Sabi")

# Step 2. Join the datasets by the rounded datetime column
wildschwein_joined <- inner_join(
  wildschwein_rosa, wildschwein_sabi,
  by = "DatetimeRound",  # Joining on rounded timestamps
  suffix = c("_Rosa", "_Sabi")  # Add suffixes to distinguish columns
)
# print(wildschwein_joined)

# Step 3. Calculate Euclidean distance
wildschwein_joined <- wildschwein_joined %>%
  mutate(
    distance_m = sqrt((E_Rosa - E_Sabi)^2 + (N_Rosa - N_Sabi)^2)
  )

# Step 4: Define a "meeting" based on a 100-meter threshold
wildschwein_joined <- wildschwein_joined %>%
  mutate(
    is_meeting = distance_m <= 100  # TRUE if distance is 100m or less
  )

wildschwein_meets <- wildschwein_joined %>%
  filter(is_meeting == TRUE)

Task 5: Visualize data

ggplot() +
  # Plot all locations for Rosa
  geom_point(data = wildschwein_rosa, aes(x = E, y = N), color = "red", alpha = 0.5, size = 2) +
  
  # Plot all locations for Sabi
  geom_point(data = wildschwein_sabi, aes(x = E, y = N), color = "darkgreen", alpha = 0.5, size = 2) +
  
  # Highlight the meet locations
  geom_point(data = wildschwein_meets, aes(x = E_Rosa, y = N_Rosa), color = "black", size = 4, shape = 8) +
  
  # Manually set axis limits (adjust based on your dataset)
  xlim(min(wildschwein$E) - 50, max(wildschwein$E) + 50) +
  ylim(min(wildschwein$N) - 50, max(wildschwein$N) + 50) +
  
  # Add labels and theme
  labs(
    title = "Spatial Visualisation of Rosa (rot) and Sabi (grün)",
    subtitle = "Black stars (*) indicate meets",
    x = "Easting (E)", y = "Northing (N)"
  ) +
  theme_minimal()

Task 6 (optional): Visualize data as timecube with plotly

# install.packages("plotly")
library("plotly")
Warning: Paket 'plotly' wurde unter R Version 4.4.3 erstellt

Attache Paket: 'plotly'
Das folgende Objekt ist maskiert 'package:ggplot2':

    last_plot
Das folgende Objekt ist maskiert 'package:stats':

    filter
Das folgende Objekt ist maskiert 'package:graphics':

    layout
# Schritt 1: Stellen Sie sicher, dass TimeNum korrekt berechnet wird
min_time <- min(wildschwein$DatetimeUTC, na.rm = TRUE)

# Berechnung von TimeNum für den gesamten wildschwein-Datensatz
wildschwein <- wildschwein %>%
  mutate(TimeNum = as.numeric(difftime(DatetimeUTC, min_time, units = "hours")))  # Zeit in Stunden

# Berechnung von TimeNum für den wildschwein_meets-Datensatz
wildschwein_meets <- wildschwein_joined %>%
  filter(is_meeting == TRUE) %>%
  mutate(TimeNum = as.numeric(difftime(DatetimeRound, min_time, units = "hours")))  # Zeit in Stunden
# 3D Space-Time-Cube Plot erstellen
library(plotly)

plot_ly() %>%
  # Trajektorie von Rosa (rote Linie)
  add_trace(
    data = wildschwein_rosa,
    type = 'scatter3d',
    x = ~E,
    y = ~N,
    z = ~as.numeric(DatetimeRound),
    mode = 'lines',
    name = 'Rosa',
    line = list(color = 'red')
  ) %>%
  # Trajektorie von Sabi (blaue Linie)
  add_trace(
    data = wildschwein_sabi,
    type = 'scatter3d',
    x = ~E,
    y = ~N,
    z = ~as.numeric(DatetimeRound),
    mode = 'lines',
    name = 'Sabi',
    line = list(color = 'blue')
  ) %>%
  # Treffpunkte (schwarze Punkte)
  add_trace(
    data = wildschwein_meets,
    type = 'scatter3d',
    x = ~E_Rosa,
    y = ~N_Rosa,
    z = ~as.numeric(DatetimeRound),
    mode = 'markers',
    name = 'Meets',
    marker = list(color = 'black', size = 4)
  ) %>%
  # Layout und Achsenbeschriftungen
  layout(
    title = 'Space-Time Cube: Rosa & Sabi Meets',
    scene = list(
      xaxis = list(title = 'Easting (E)'),
      yaxis = list(title = 'Northing (N)'),
      zaxis = list(title = 'Time (Datetime)'),
      aspectmode = 'cube'
    )
  )