Key movement variables: speed, altitude, turning angle, vertical rate
Goal: uncover structure in movement behavior using PCA
PCA summarizes high-dimensional movement patterns into principal components
PCA Methods
Variables included in PCA:
KPH, Sn, AGL, abs_angle, VerticalRate, absVR
Data standardized before PCA
Principal Components capture major axes of movement variation
Scree Plot
PCA Variable Plot
PCA Scores (PC1 vs PC2)
Transition to Clustering
PCA showed clear variation in movement based on speed, turning, and vertical motion.
The spread of points in PCA space suggests the presence of distinct movement patterns.
PCA explains structure, but clustering helps identify actual behavioral groups.
Next, I apply clustering methods to define and interpret these movement states.
Bootstrapped Silhouette Curve for K = 2–7
Bootstrap WSS Curve Plot
PCA Plot w/ Cluster Labels
How Movement Variables Differ Across Clusters
Appendix
Data Loading and Transformations
library(tidyverse)library(readxl)library(vegan)library(cluster)library(factoextra)library(ggrepel)library(purrr)# Load base datasetload("eagle_data.Rdata")# Apply transformations recommended in movement ecology literature# Square-root reduces right skew for positive variables# VerticalRate (VR) left untransformed per original methodologyeagle_tr <- eagle_data %>%mutate(KPH_tr =sqrt(KPH),Sn_tr =sqrt(Sn),AGL_tr =sqrt(AGL),abs_angle_tr =sqrt(abs_angle),VR_tr = VerticalRate, # leave untransformedabsVR_tr =sqrt(absVR) ) %>%# keep Animal_ID attachedmutate(Animal_ID = Animal_ID) %>%# remove rows where any transformed movement variable is missingdrop_na(KPH_tr, Sn_tr, AGL_tr, abs_angle_tr, VR_tr, absVR_tr)# List of transformed variables used for PCA and clusteringvars_tr <-c("KPH_tr", "Sn_tr", "AGL_tr", "abs_angle_tr", "VR_tr", "absVR_tr")
Stratified Sampling for Clustering Code
points_per_eagle <-5000set.seed(123)df_strat <- eagle_tr %>%group_by(Animal_ID) %>%# keep equal representation per eaglesample_n(points_per_eagle, replace =TRUE) %>%ungroup()# Scaled matrix used for k-means clusteringX_strat <-scale(df_strat %>%select(all_of(vars_tr)))