Figure 1:
library(ggplot2) #loading ggplot package
library(tidyverse) #loading tidyverse package
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.2.1 ✔ readr 2.2.0
## ✔ forcats 1.0.1 ✔ stringr 1.6.0
## ✔ lubridate 1.9.5 ✔ tibble 3.3.1
## ✔ purrr 1.2.2 ✔ tidyr 1.3.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
install.packages("factoextra") #install factoextra package for pca
## Installing package into '/cloud/lib/x86_64-pc-linux-gnu-library/4.5'
## (as 'lib' is unspecified)
library(factoextra) #loading factoextra package
## Welcome to factoextra!
## Want to learn more? See two factoextra-related books at https://www.datanovia.com/en/product/practical-guide-to-principal-component-methods-in-r/
library(ggrepel) #loading in ggrepel, to fix overlapping text in pca graph
library(patchwork) #loading in patchwork, to put the m/f pca plots side-by-side and enhance male barplot figure
Bluebird_Data <- read_csv("Bluebird_Data.csv") #loading in eastern bluebird dataset
## Rows: 250 Columns: 20
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (5): BIRDSEX, NS_GP2, DATE, TIME, NOISE
## dbl (15): BIRDID, NEST, CLUTCH, PEEK, POKE, GAPE, ONBOX, ATHOLE, IN, OUT, PB...
##
## ℹ 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.
male <- Bluebird_Data %>% #split up data
filter(BIRDSEX == "M") #filter by males only
fem <- Bluebird_Data %>% #split up data
filter(BIRDSEX == "F") #filter by females only
f_behaviors <- c("POKE", "PEEK", "GAPE", "ONBOX") #define female behavior categories
m_behaviors <- c("ATHOLE", "OUT", "IN", "ONBOX") #define male behavior categories
m_data <- male %>% #refine data
select(all_of(m_behaviors)) %>% #incl all above behavior variables
na.omit() #omit N/A data
m_pca <- prcomp(m_data, scale. = TRUE) #setting up male only PCA
m_df <- as.data.frame(m_pca$x) #final dataframe for ggplotting
m_loadings <- as.data.frame(m_pca$rotation) #define 'loadings' for male data
m_loadings$var <- rownames(m_loadings) #define 'var' to use place of rownames
m_plot <- ggplot(data = m_df, aes(x = PC1, y = PC2)) + #specify dataset & x/y axes
geom_point(color= "royalblue3", size=4, shape=18, alpha= 0.7) + #point color, size, shape
geom_segment(data = m_loadings, #create segments with loadings
aes(x=0, y=0, xend = PC1, yend = PC2), #choose segment x/y end
inherit.aes = FALSE,
color = "magenta2") + #color arrows on loading plot
geom_text_repel(data = m_loadings, #fixing overlapping text on loading plot
aes(PC1, PC2, label = var, #set x/y axes and specify segments lead to rownames (containing target behaviors)
fontface = "bold"))+ #make labels bold
theme_gray() + #alter theme to incl light gray background
ggtitle("Male Bluebird PCA") + #title
coord_cartesian(xlim= c(-1,3), ylim= c(-2, 3)) #set x/y limits to 'zoom in' on the data
f_data <- fem %>% #refine data
select(all_of(f_behaviors)) %>% #incl all above behavior variables
na.omit() #omit N/A data
f_pca <- prcomp(f_data, scale. = TRUE) #setting up female only PCA
f_df <- as.data.frame(f_pca$x) #final dataframe for ggplotting
f_loadings <- as.data.frame(f_pca$rotation) #define 'loadings' for females
f_loadings$var <- rownames(f_loadings) #define 'var' to use place of rownames
f_plot <- ggplot(data = f_df, aes(x = PC1, y = PC2)) + #specify dataset & x/y axes
geom_point(color= "magenta3", size=4, shape=18, alpha = 0.7) + #point color, size, shape
geom_segment(data = f_loadings, #create segments with loadings
aes(x=0, y=0, xend = PC1, yend = PC2), #choose segment x/y end
inherit.aes = FALSE,
color = "royalblue") + #color arrows on loading plot
geom_text_repel(data = f_loadings, #fixing overlapping text on loading plot
aes(PC1, PC2, label = var, #set x/y axes and specify segments lead to rownames (containing target behaviors)
fontface = "bold"))+ #make labels bold
theme_gray() + #alter theme to incl light gray background
ggtitle("Female Bluebird PCA") + #title
coord_cartesian(xlim= c(-1,3), ylim= c(-2, 3)) #set x/y limits to 'zoom in' on the data
m_plot + f_plot #display the two plots side-by-side

Figure 2:
library(cowplot) #loading in cowplot package for adding small zoom-in window of male data
##
## Attaching package: 'cowplot'
## The following object is masked from 'package:patchwork':
##
## align_plots
## The following object is masked from 'package:lubridate':
##
## stamp
bluebirds <- Bluebird_Data %>% #alter & rename the data
group_by(BIRDSEX, NS_GP2) %>% #group data by sex & noise category
summarise(across(c(PEEK, POKE, GAPE, ONBOX), #create summary data across target behaviors
list(
Mean = ~mean(.x, na.rm = TRUE), #define "Mean"
SE = ~sd(.x, na.rm = TRUE) / sqrt(sum(!is.na(.x))) #define "SE"
)),
.groups = "drop") #tidying up
long_birds <- bluebirds %>% #alter & rename the data again to pivot it longer
pivot_longer(cols= -c(BIRDSEX, NS_GP2), #pivot the data
names_to = c("Behavior", ".value"), #name new column
names_sep = "_") #new column for mean data
fig.2 <- ggplot(long_birds, aes(x= NS_GP2, y= Mean, fill= Behavior))+ #graph by noise category, mean, & fill by behavior
geom_bar(position= position_dodge(width= 1), stat= "identity") + #create grouped barplot & specify width
geom_errorbar(aes(ymin= Mean-SE, ymax= Mean + SE), #create SE bars, specifying the max/min error bar values
position = position_dodge(width=1), #error bar position & width
width = 0.5)+ #error bar top/bottom line width
facet_wrap(~BIRDSEX, scales='free') + #facet wrap to have both male & female graphs side-by-side
labs(
x = "Noise Categories", #x axis title
y = "Mean Behavior per Hour", #y axis title
title = "Average Observed Behavior by Noise Category") + #figure title
theme_bw() #selected theme
fig.2.zoom <- long_birds %>% #creating zoomed-in version of males only
dplyr::filter(BIRDSEX == "M",
NS_GP2 %in% c("Q", "QPI", "QPA")) %>% #only include male data
ggplot(aes(x= NS_GP2, y= Mean, fill= Behavior)) + #ploting noise category, mean, and fill by behavior type
geom_bar(position= position_dodge(width= 1), stat= "identity") + #create grouped barplot & specify width
geom_errorbar(aes(ymin= Mean-SE, ymax= Mean + SE), #create SE bars, specifying the max/min error bar values
position = position_dodge(width=1), #error bar position & width
width = 0.5)+ #error bar top/bottom line width
coord_cartesian(ylim = c(0, 0.3)) + #specify zoom-in max/min
theme_bw() + #select theme
theme(legend.position = "none", #no legend
axis.title.x = element_blank(), #no x axis title
axis.title.y = element_blank()) #no y axis title
ggdraw() + #combine the original figure and the zoomed in figure
draw_plot(fig.2) +
draw_plot(fig.2.zoom, x= 0.54, y= 0.57, #input zoomed figure, x/y indicate location on graph (as close as possible w/o touching the edges)
width = 0.3, height = 0.3) #specify the zoomed view size
