SETUP
setwd(“D:/adult shit/Career/Masters/S2026/Capstone/R”)
if (!requireNamespace(“pacman”, quietly = TRUE)) { install.packages(“pacman”) }
library(pacman) p_load( tidyverse, RColorBrewer, glmmTMB, emmeans, openxlsx, ggpubr, paletteer, ggrepel )
olive_data <- read.xlsx( “Olive PTSD Raw Data (for Chandler).xlsx”, sheet = 1, colNames = TRUE )
DATA CLEANING
olive_data <- olive_data %>%
select(-Configuration.Name, -Date, -Time, -Observer,
-DeviceID, -Edited, -Session.Start.Time,
-Recorded.Start.Time, -Session.End.Time,
-Month, -Hour, -Project.Animals, -Duration,
-Habitat.Map, -Grid.Size,
-Image.Size, -Notes, -Subject.Type,
-Focal.Name, -Group.Count,
-Interval.Channel.1.Name,
-Question:.Type.of.Data.Collection_133,
-Question:.Indoor/Outdoor?_49 )
olive_data <- olive_data %>% rename( Behavior_Channel =
Channel.Type, All_Occurrence_Behavior =
All.Occurrence.Value, All_Occurrence_Behavior_Modifier_1 =
All.Occurrence.Behavior.Modifier.1,
Continuous_Channel_1_Name = Continuous.Channel.1.Name,
Continuous_Channel_1_Behavior = Continuous.Channel.1.Value,
Continuous_Channel_1_Duration_s =
Continuous.Channel.1.Duration.(sec),
Continuous_Channel_2_Name = Continuous.Channel.2.Name,
Continuous_Channel_2_Behavior = Continuous.Channel.2.Value,
Continuous_Channel_2_Duration_s =
Continuous.Channel.2.Duration.(sec), Frame_Number =
Frame.Number, Interval_Scan_Behavior =
Interval.Channel.1.Value, Interval_Scan_Modifier =
Interval.Channel.1.Behavior.Modifier.1,
Human_Presence_Last_30s = Interval.Channel.2.Name,
Human_Present_Win_5BL = Interval.Channel.2.Value,
Conspecific_Proximity = Interval.Channel.3.Name, BL_Dist =
Interval.Channel.3.Value, Video_File_Name =
Question:.Video.File.Name_46, Date =
Question:.Date_41, Time = Question:.Time_42,
Phase = Question:.Phase.of.Data.Collection_44,
Temp(F) = Question:.Temperature.(F)_47,
Wind_Speed(mph) =
Question:.Wind.Speed.(mph)_48, Weather_Condition =
Question:.Weather.Condition_45 )
olive_data\(Date <- as.Date(olive_data\)Date, origin = “1899-12-30”)
olive_data <- olive_data %>% mutate( Time = as.numeric(as.character(Time)), # convert factor/char to numeric Time = format( as.POSIXct(Time * 24 * 60 * 60, origin = “1970-01-01”, tz = “UTC”), “%H:%M” ) )
olive_data <- olive_data %>% mutate( # Set both Interval_Scan_Behavior and Interval_Scan_Modifier to NA when ‘Out of View’ is recorded Interval_Scan_Behavior = ifelse(Interval_Scan_Behavior == “Out of View”, NA, Interval_Scan_Behavior), Interval_Scan_Modifier = ifelse(Interval_Scan_Behavior == “Out of View”, NA, Interval_Scan_Modifier) )
olive_data <- olive_data %>% mutate( Human_Presence = ifelse( is.na(Human_Presence_Last_30s) | Human_Presence_Last_30s != “Humans Present (within the last 30 seconds)”, 0, 1 ), Human_Presence = factor(Human_Presence, levels = c(0, 1), labels = c(“Absent”, “Present”)) )
start_date <- as.Date(“2024-11-27”)
olive_data <- olive_data %>% mutate( Week_Number = 1 + floor(as.numeric(difftime(Date, start_date, units = “days”)) / 7) )
DESCRIPTIVE STATS
scan_behaviors <- olive_data %>% filter(Behavior_Channel == “Interval”) %>% mutate( scan_behavior = if_else( !is.na(Interval_Scan_Modifier), paste(Interval_Scan_Behavior, Interval_Scan_Modifier, sep = “_“), Interval_Scan_Behavior ) )
scan_behavior_rates <- scan_behaviors %>% count(scan_behavior) %>% mutate( total_intervals = sum(n), occurrence_rate = n / total_intervals )
all_occurrence_behaviors <- olive_data %>% filter(Behavior_Channel == “All Occurrence”) %>% mutate( behavior_combined = if_else( !is.na(All_Occurrence_Behavior_Modifier_1), paste(All_Occurrence_Behavior, All_Occurrence_Behavior_Modifier_1, sep = “_“), All_Occurrence_Behavior ) )
all_occurrence_rates <- all_occurrence_behaviors %>% count(behavior_combined) %>% mutate( total_events = sum(n), occurrence_rate = n / total_events )
continuous_behaviors <- olive_data %>% filter(Behavior_Channel == “Continuous”) %>% select( SessionID, Date, Time, Phase, Continuous_Channel_1_Behavior, Continuous_Channel_1_Duration_s, Continuous_Channel_2_Behavior, Continuous_Channel_2_Duration_s ) %>% pivot_longer( cols = -c(SessionID, Date, Time, Phase), names_to = c(“channel”, “.value”), names_pattern = “Continuous_Channel_(\d+)_(.*)” ) %>% filter(!is.na(Behavior), !is.na(Duration_s))
continuous_behavior_rates <- continuous_behaviors %>% group_by(Behavior) %>% summarise( total_duration_min = sum(Duration_s, na.rm = TRUE) / 60, n_sessions = n_distinct(SessionID), minutes_per_hour = (total_duration_min / n_sessions) * 2, # scale 30-min session to per-hour percent_of_hour = (minutes_per_hour / 60) * 100, .groups = “drop” )
scan_behavior_phase <- scan_behaviors %>% group_by(Phase, scan_behavior) %>% summarise(n = n(), .groups = “drop”) %>% group_by(Phase) %>% mutate( total_intervals = sum(n), occurrence_rate = n / total_intervals ) %>% ungroup()
scan_behavior_phase <- scan_behavior_phase %>% mutate( occurrences_per_hour = occurrence_rate * 120 )
all_occurrence_phase <- all_occurrence_behaviors %>% group_by(SessionID, Phase, All_Occurrence_Behavior) %>% summarise(n = n(), .groups = “drop”) %>% # 30min -> 1hr mutate(events_per_hour = n * 2)
all_occurrence_avg <- all_occurrence_phase %>% group_by(Phase, All_Occurrence_Behavior) %>% summarise( mean_events_per_hour = mean(events_per_hour), .groups = “drop” )
continuous_behavior_phase <- continuous_behaviors %>% group_by(Phase, Behavior) %>% summarise( total_duration_min = sum(Duration_s, na.rm = TRUE) / 60, n_sessions = n_distinct(SessionID), minutes_per_hour = (total_duration_min / n_sessions) * 2, .groups = “drop” ) %>% ungroup()
#Human presence by phase humans_by_phase <- olive_data %>% group_by(Phase) %>% summarise( total_intervals = n(), human_occurrences = sum(!is.na(Human_Present_Win_5BL)), occurrence_rate = mean(!is.na(Human_Present_Win_5BL)), .groups = “drop” )
P3_proximity <- olive_data %>% filter(Phase == 3)
P3_proximity <- P3_proximity %>% select( SessionID, Conspecific_Proximity, BL_Dist, Video_File_Name, Date, Time, Week_Number )
BLDist_count <- olive_data %>% filter(Phase == 3, !is.na(BL_Dist)) %>% # remove BL_Dist NA first group_by(Week_Number, BL_Dist) %>% summarise(count = n(), .groups = “drop”) %>%
mutate( BL_Dist = factor(BL_Dist, levels = c(“Contact”, “<1 body length”, “1-5 body lengths”)),
P3_week = case_when(
Week_Number == 20 ~ "1",
Week_Number == 21 ~ "2",
TRUE ~ NA_character_
)
) %>%
filter(!is.na(P3_week), !is.na(BL_Dist))
scan_behavior_phase %>% filter(!is.na(scan_behavior)) %>% ggplot(aes(x = Phase, y = occurrences_per_hour, fill = scan_behavior)) + geom_col(position = “dodge”) + scale_fill_viridis_d(option = “turbo”) + labs( title = “Scan Behavior Rates Between Phases”, x = “Phase”, y = “Time Spent Performing Behavior (min/hr)”, fill = “Behavior” ) + theme_minimal()
all_occurrence_avg %>% ggplot(aes(x = Phase, y = mean_events_per_hour, fill = All_Occurrence_Behavior)) + geom_col(position = “dodge”) + scale_fill_viridis_d(option = “turbo”) + labs( title = “Average Rate of All Occurrence Behaviors Between Phases”, x = “Phase”, y = “All Occurrence Events/hr”, fill = “Behavior” ) + theme_minimal()
continuous_behavior_phase %>% filter(!is.na(Behavior)) %>% ggplot(aes(x = Phase, y = minutes_per_hour, fill = Behavior)) + geom_col(position = “dodge”) + scale_fill_viridis_d(option = “turbo”) + labs( title = “Duration of Continuous Behaviors Between Phases”, x = “Phase”, y = “Time Spent Performing Continuous Behavior (min/hr)”, fill = “Behavior” ) + theme_minimal()
BLDist_count %>% filter(!is.na(BL_Dist), !is.na(P3_week)) %>% ggplot(aes(x = BL_Dist, y = count, fill = P3_week)) + geom_col(position = “dodge”) + scale_fill_viridis_d(option = “turbo”) + labs( title = “Phase 3 Proximity Counts by Week”, x = “Distance Category”, y = “Count”, fill = “P3 Week” ) + theme_minimal()
ACTIVITY BUDGETS
budget_data <- olive_data
budget_scans <- budget_data %>% filter(Behavior_Channel == “Interval”) %>% filter(!is.na(Interval_Scan_Behavior)) %>% filter(Interval_Scan_Behavior != “Out of View”) %>% mutate( behavior = Interval_Scan_Behavior, time_sec = 30 ) %>% select(behavior, time_sec)
budget_allocc <- budget_data %>% filter(Behavior_Channel == “All Occurrence”) %>% filter(!is.na(All_Occurrence_Behavior)) %>% mutate( behavior = All_Occurrence_Behavior, time_sec = 1 ) %>% select(behavior, time_sec)
budget_continuous_raw <- budget_data %>% filter(Behavior_Channel == “Continuous”)
continuous_long_1 <- budget_continuous_raw %>% transmute( behavior = Continuous_Channel_1_Behavior, time_sec = Continuous_Channel_1_Duration_s ) %>% filter(!is.na(behavior), !is.na(time_sec))
continuous_long_2 <- budget_continuous_raw %>% transmute( behavior = Continuous_Channel_2_Behavior, time_sec = Continuous_Channel_2_Duration_s ) %>% filter(!is.na(behavior), !is.na(time_sec))
budget_scans_phase <- budget_data %>% filter(Behavior_Channel == “Interval”) %>% filter(!is.na(Interval_Scan_Behavior)) %>% filter(Interval_Scan_Behavior != “Out of View”) %>% mutate( behavior = Interval_Scan_Behavior, time_sec = 30 ) %>% select(Phase, behavior, time_sec)
budget_allocc_phase <- budget_data %>% filter(Behavior_Channel == “All Occurrence”) %>% filter(!is.na(All_Occurrence_Behavior)) %>% mutate( behavior = All_Occurrence_Behavior, time_sec = 1 ) %>% select(Phase, behavior, time_sec)
continuous_long_1 <- budget_continuous_raw %>% transmute( Phase, behavior = Continuous_Channel_1_Behavior, time_sec = Continuous_Channel_1_Duration_s ) %>% filter(!is.na(behavior), !is.na(time_sec))
continuous_long_2 <- budget_continuous_raw %>% transmute( Phase, behavior = Continuous_Channel_2_Behavior, time_sec = Continuous_Channel_2_Duration_s ) %>% filter(!is.na(behavior), !is.na(time_sec))
budget_continuous <- bind_rows(continuous_long_1, continuous_long_2)
budget_combined_phase <- bind_rows( budget_scans_phase, budget_allocc_phase, budget_continuous )
budget_phase_summary <- budget_combined_phase %>% group_by(Phase, behavior) %>% summarise( total_time = sum(time_sec), .groups = “drop” ) %>% group_by(Phase) %>% mutate( proportion = total_time / sum(total_time) ) %>% ungroup()
ggplot(budget_phase_summary, aes(x = ““, y = proportion, fill = behavior)) + geom_col(width = 1) + coord_polar(theta =”y”) + facet_wrap(~ Phase) +
# ADD LABELS geom_text( aes(label = ifelse(proportion > 0.10, scales::percent(proportion, accuracy = 0.1), ““)), position = position_stack(vjust = 0.5), size = 3 ) +
scale_fill_viridis_d(option = “turbo”) + theme_void() + labs( title = “Activity Budget Between Phases (All Behavior Channels Combined)”, fill = “Behavior” )
scan_plot_data <- budget_scans_phase %>% group_by(Phase, behavior) %>% summarise(n = n(), .groups = “drop”) %>% group_by(Phase) %>% mutate( proportion = n / sum(n), percent = proportion * 100, label_inside = ifelse(percent > 5, paste0(round(percent, 1), “%”), NA), label_outside = ifelse(percent <= 5, paste0(behavior, ” (“, round(percent, 1),”%)“), NA) ) %>% ungroup()
ggplot(scan_plot_data, aes(x = 1, y = proportion, fill = behavior)) + geom_col(width = 1) + coord_polar(theta = “y”) + facet_wrap(~ Phase) + scale_fill_viridis_d(option = “turbo”) +
geom_text(aes(label = label_inside), position = position_stack(vjust = 0.5), color = “black”, size = 4, na.rm = TRUE) +
guides(fill = guide_legend(title = “Behavior”)) +
labs( title = “Scan Behavior Budget Between Phases”, fill = “Behavior” ) + theme_void()
budget_allocc_cont <- bind_rows( budget_allocc_phase, budget_continuous )
allocc_cont_plot_data <- budget_allocc_cont %>% group_by(Phase, behavior) %>% summarise(total_time = sum(time_sec), .groups = “drop”) %>% group_by(Phase) %>% mutate( proportion = total_time / sum(total_time), percent = proportion * 100, label_inside = ifelse(percent > 5, paste0(round(percent, 1), “%”), NA), label_outside = ifelse(percent <= 5, paste0(behavior, ” (“, round(percent, 1),”%)“), NA) ) %>% ungroup()
ggplot(allocc_cont_plot_data, aes(x = 1, y = proportion, fill = behavior)) + geom_col(width = 1) + coord_polar(theta = “y”) + facet_wrap(~ Phase) + scale_fill_viridis_d(option = “turbo”) +
geom_text(aes(label = label_inside), position = position_stack(vjust = 0.5), color = “black”, size = 4, na.rm = TRUE) +
labs( title = “Stress-related Budget Between Phases”, fill = “Behavior” ) + theme_void()
scan_plot_data <- budget_scans %>% group_by(behavior) %>% summarise( n = n(), .groups = “drop” ) %>% mutate( proportion = n / sum(n) )
ggplot(scan_plot_data, aes(x = ““, y = proportion, fill = behavior)) + geom_col(width = 1) + coord_polar(theta =”y”) + scale_fill_viridis_d(option = “turbo”) + labs( title = “Activity Budget: Interval Scan Behaviors”, fill = “Behavior” ) + theme_void() +
geom_text( aes(label = scales::percent(proportion, accuracy = 0.1)), position = position_stack(vjust = 0.5), size = 3 )
allocc_plot_data <- budget_allocc %>% group_by(behavior) %>% summarise( total_time = sum(time_sec), .groups = “drop” ) %>% mutate( proportion = total_time / sum(total_time) )
ggplot(allocc_plot_data, aes(x = ““, y = proportion, fill = behavior)) + geom_col(width = 1) + coord_polar(theta =”y”) + scale_fill_viridis_d(option = “turbo”) + theme_void() + labs( title = “Activity Budget: All Occurrence Behaviors”, fill = “Behavior” )
budget_continuous <- bind_rows(continuous_long_1, continuous_long_2)
continuous_plot_data <- budget_continuous %>% group_by(behavior) %>% summarise( total_time = sum(time_sec), .groups = “drop” ) %>% mutate( proportion = total_time / sum(total_time) )
ggplot(continuous_plot_data, aes(x = ““, y = proportion, fill = behavior)) + geom_col(width = 1) + coord_polar(theta =”y”) + scale_fill_viridis_d(option = “turbo”) + theme_void() + labs( title = “Activity Budget: Continuous Behaviors”, fill = “Behavior” )
budget_combined <- bind_rows( budget_scans, budget_allocc, budget_continuous )
budget_summary <- budget_combined %>% group_by(behavior) %>% summarise( total_time = sum(time_sec), .groups = “drop” ) %>% mutate( proportion = total_time / sum(total_time) )
ggplot(budget_summary, aes(x = ““, y = proportion, fill = behavior)) + geom_col(width = 1) + coord_polar(theta =”y”) + scale_fill_viridis_d(option = “turbo”) + theme_void() + labs( title = “Activity Budget (All Behavior Channels Combined)”, fill = “Behavior” )