Preliminaries
Load libraries
library(knitr) #for R Markdown
library(MASS) #for negative binomial glm (glm.nb)
library(lme4) #for mixed models
library(emmeans) #for posthoc
library(car) #for Anova
library(survival) #for survival analysis
library(coxme)
library(rptR) #for repeatability analysis
library(MuMIn) #for model selection (dredge)
library(ggfortify) #for plotting survival analysis
library(ggsignif) #for labeling significance in ggplots
library(GGally) #for correlation matrix
library(tidyverse) #for data processing, put last to avoid function masking
Data processing
Read dataset, correct variable types, and derive variables.
data_raw <- read.csv("data_personality_final_030126.csv",
# to avoid reading errors
fileEncoding="UTF-8-BOM", na.strings = c("","N/A","#VALUE!"))
data <- data_raw %>%
#clean up some entries for easier analysis
mutate(gosner_stage = ifelse(gosner_stage=="45/46", 46, as.integer(gosner_stage))) %>%
mutate(tadpole_ID = factor(paste0("T", tadpole_ID), levels = paste0("T", sort(unique(tadpole_ID))))) %>%
#correct variable types
mutate_at(c("tadpole_ID","morph","water_y.n"), as.factor) %>%
mutate_at(c("found_date","assay_date_OF","assay_date_shelter"), lubridate::mdy) %>%
mutate_at(c("invisible_time_hh_mm_ss"), lubridate::hms) %>%
mutate_at("exploration_rate_explored_div_by_total", as.numeric) %>%
#derive variables
mutate(condition = body_width_mm/length_without_tail_mm,
age = assay_date_OF - found_date,
age = if_else(age < 0, NA, age)) %>%
#add trial sequence for each tadpole
arrange(tadpole_ID, week, replicate) %>%
group_by(tadpole_ID) %>%
mutate(trial_seq = row_number()) %>%
ungroup()
Sample sizes
data %>% select(tadpole_ID, week) %>% table
## week
## tadpole_ID 1 2 3 4 5 6 7 8 9
## T5 4 4 4 4 4 0 0 0 0
## T6 4 4 4 4 4 0 0 0 0
## T7 4 4 4 4 4 0 0 0 0
## T8 4 4 4 4 4 4 4 4 4
## T9 4 4 4 4 4 0 0 0 0
## T10 4 4 4 4 4 0 0 0 0
## T11 4 4 4 4 4 0 0 0 0
## T12 4 4 4 4 4 0 0 0 0
## T13 4 4 4 4 4 4 0 0 0
## T14 4 4 4 4 4 0 0 0 0
## T15 4 4 4 4 4 0 0 0 0
## T16 4 4 4 4 4 0 0 0 0
## T17 4 4 4 4 0 0 0 0 0
## T18 4 4 4 4 0 0 0 0 0
## T19 4 4 4 4 0 0 0 0 0
## T20 4 4 4 4 0 0 0 0 0
## T21 4 4 4 4 0 0 0 0 0
## T22 4 4 4 4 0 0 0 0 0
## T23 4 4 4 4 0 0 0 0 0
## T24 4 4 4 4 0 0 0 0 0
## T25 4 4 4 4 0 0 0 0 0
## T26 4 4 4 4 0 0 0 0 0
## T27 4 4 4 4 0 0 0 0 0
## T28 4 4 4 4 0 0 0 0 0
## T29 4 4 4 4 4 0 0 0 0
## T30 4 4 4 4 4 0 0 0 0
## T31 4 4 4 4 0 0 0 0 0
## T32 4 4 4 4 4 0 0 0 0
## T33 4 4 4 4 4 0 0 0 0
## T34 4 4 4 4 0 0 0 0 0
## T35 4 4 4 4 4 0 0 0 0
data %>% select(tadpole_ID, gosner_stage) %>% table
## gosner_stage
## tadpole_ID 26 30 31 36 37 41 42 45 46
## T5 3 16 0 0 0 0 0 0 0
## T6 3 0 0 4 0 2 2 2 6
## T7 4 4 0 0 0 4 4 0 4
## T8 8 16 4 0 0 4 0 0 4
## T9 4 4 0 0 0 4 4 0 4
## T10 0 4 2 0 2 4 0 0 8
## T11 0 8 2 0 0 2 4 0 4
## T12 0 6 2 0 2 0 6 0 4
## T13 0 24 0 0 0 0 0 0 0
## T14 0 6 2 0 0 4 4 0 4
## T15 4 4 0 0 0 4 4 0 4
## T16 4 4 0 0 0 6 2 0 4
## T17 4 2 0 0 0 4 0 0 4
## T18 0 0 4 0 2 4 2 0 4
## T19 0 0 4 0 2 2 4 0 4
## T20 0 0 4 0 2 2 4 0 4
## T21 0 0 6 0 2 2 2 0 4
## T22 0 0 4 0 0 4 4 0 4
## T23 0 0 4 0 0 4 4 0 4
## T24 0 0 4 0 2 6 0 0 4
## T25 0 0 4 0 4 4 0 0 4
## T26 4 0 0 0 4 4 0 0 4
## T27 0 0 4 0 2 2 4 0 4
## T28 4 0 0 0 4 4 0 0 4
## T29 4 0 0 0 4 4 4 0 4
## T30 2 0 2 0 4 4 0 0 8
## T31 0 0 4 0 0 4 4 0 4
## T32 4 0 0 0 4 4 0 4 4
## T33 4 0 4 0 0 4 4 0 4
## T34 0 0 4 0 0 4 2 2 4
## T35 4 0 0 0 4 4 4 0 4
Developmental rate
#set highlighter colors
tad_ids <- unique(data$tadpole_ID)
color_highlights <- setNames(rep("grey80", length(tad_ids)), tad_ids)
# Assign distinct colors to weirdo tadpoles
color_highlights ["T5"] <- "#3B1C8C"
color_highlights ["T8"] <- "#56B4E9"
color_highlights ["T13"] <- "#21908C"
ggplot(data %>% filter(),
aes(x = age, y = gosner_stage, group = tadpole_ID, color = tadpole_ID)) +
geom_line(alpha = 0.9, size = 1) +
labs(x = "Age (days)", y = "Gosner stage") +
scale_color_manual(values = color_highlights, breaks = c("T5", "T8", "T13")) +
theme_classic(base_size = 18)

T5, T8 & T13 are the weirdos that didn’t develop/develop slow,
remove from all analysis. Removing G46 data as well, since they are dry
in assays and hard to compare
data_filt <- data %>%
filter(!tadpole_ID %in% c("T5","T8","T13"),
water_y.n !="n",
gosner_stage != 46) %>%
droplevels()
sample sizes w/o outliers
data_filt %>% select(tadpole_ID, week) %>% table()
## week
## tadpole_ID 1 2 3 4
## T6 3 4 4 2
## T7 4 4 4 4
## T9 4 4 4 4
## T10 4 4 4 0
## T11 4 4 4 4
## T12 4 4 4 4
## T14 4 4 4 4
## T15 4 4 4 4
## T16 4 4 4 4
## T17 4 2 4 0
## T18 4 4 4 0
## T19 4 4 0 0
## T20 4 4 4 0
## T21 4 4 4 0
## T22 4 4 4 0
## T23 4 4 4 0
## T24 4 4 4 0
## T25 4 4 4 0
## T26 4 4 4 0
## T27 4 4 4 0
## T28 4 4 4 0
## T29 4 4 4 4
## T30 4 4 4 0
## T31 4 4 4 0
## T32 4 4 4 4
## T33 4 4 4 4
## T34 4 4 4 0
## T35 4 4 4 4
data_filt %>% select(tadpole_ID, gosner_stage) %>% table()
## gosner_stage
## tadpole_ID 26 30 31 36 37 41 42 45
## T6 3 0 0 4 0 2 2 2
## T7 4 4 0 0 0 4 4 0
## T9 4 4 0 0 0 4 4 0
## T10 0 4 2 0 2 4 0 0
## T11 0 8 2 0 0 2 4 0
## T12 0 6 2 0 2 0 6 0
## T14 0 6 2 0 0 4 4 0
## T15 4 4 0 0 0 4 4 0
## T16 4 4 0 0 0 6 2 0
## T17 4 2 0 0 0 4 0 0
## T18 0 0 4 0 2 4 2 0
## T19 0 0 4 0 2 2 0 0
## T20 0 0 4 0 2 2 4 0
## T21 0 0 6 0 2 2 2 0
## T22 0 0 4 0 0 4 4 0
## T23 0 0 4 0 0 4 4 0
## T24 0 0 4 0 2 6 0 0
## T25 0 0 4 0 4 4 0 0
## T26 4 0 0 0 4 4 0 0
## T27 0 0 4 0 2 2 4 0
## T28 4 0 0 0 4 4 0 0
## T29 4 0 0 0 4 4 4 0
## T30 2 0 2 0 4 4 0 0
## T31 0 0 4 0 0 4 4 0
## T32 4 0 0 0 4 4 0 4
## T33 4 0 4 0 0 4 4 0
## T34 0 0 4 0 0 4 2 2
## T35 4 0 0 0 4 4 4 0
Make a dataset with individual averages by week
data_wk_avg_filt <- data_filt %>%
group_by(tadpole_ID, week) %>%
summarise(avg_speed_mm = mean(avg_speed_mm, na.rm = TRUE),
mob_avg_speed_mm = mean(mob_avg_speed_mm, na.rm = TRUE),
mobility_rate = mean(mobility_rate, na.rm = TRUE),
exploration_rate_explored_div_by_total = mean(exploration_rate_explored_div_by_total, na.rm = TRUE),
total_distance_mm = mean(total_distance_mm, na.rm = TRUE),
total_time_frozen_s = mean(total_time_frozen_s, na.rm = TRUE),
lat_emerge = mean(lat_emerge, na.rm = TRUE),
time_uncovered = mean(time_uncovered, na.rm = TRUE),
num_crossing = mean(num_crossing, na.rm = TRUE),
.groups = "drop" #ungroup after summarise
)
Missing week data
open field assays
data_wk_avg_filt %>%
ungroup() %>%
complete(tadpole_ID, week = 1:4) %>%
filter(!is.na(mob_avg_speed_mm)) %>%
select(tadpole_ID, week) %>%
table()
## week
## tadpole_ID 1 2 3 4
## T6 1 1 1 1
## T7 1 1 1 1
## T9 1 1 1 1
## T10 1 1 1 0
## T11 1 1 1 1
## T12 1 1 1 1
## T14 1 1 1 1
## T15 1 1 1 1
## T16 1 1 1 1
## T17 1 1 1 0
## T18 1 1 1 0
## T19 1 1 0 0
## T20 1 1 1 0
## T21 1 1 1 0
## T22 1 1 1 0
## T23 1 1 1 0
## T24 1 1 1 0
## T25 1 1 1 0
## T26 1 1 1 0
## T27 1 1 1 0
## T28 1 1 1 0
## T29 1 1 1 1
## T30 1 1 1 0
## T31 1 1 1 0
## T32 1 1 1 1
## T33 1 1 1 1
## T34 1 1 1 0
## T35 1 1 1 1
shelter assays
data_wk_avg_filt %>%
ungroup() %>%
complete(tadpole_ID, week = 1:4) %>%
filter(!is.na(num_crossing)) %>%
select(tadpole_ID, week) %>%
table()
## week
## tadpole_ID 1 2 3 4
## T6 1 1 1 1
## T7 0 1 1 1
## T9 0 1 1 1
## T10 1 1 1 0
## T11 1 1 1 1
## T12 1 1 1 1
## T14 1 1 1 1
## T15 1 1 1 1
## T16 1 1 1 1
## T17 1 1 1 0
## T18 1 1 1 0
## T19 1 1 0 0
## T20 1 1 1 0
## T21 1 1 1 0
## T22 1 1 1 0
## T23 1 1 1 0
## T24 1 1 1 0
## T25 1 1 1 0
## T26 1 1 1 0
## T27 1 1 1 0
## T28 1 1 1 0
## T29 1 1 1 1
## T30 1 1 1 0
## T31 1 1 1 0
## T32 1 1 1 1
## T33 1 1 1 1
## T34 1 1 1 0
## T35 1 1 1 1
Raw data at a glance
Probably too many now to be comprehensible, but let’s still look at
them!
Average speed
ggplot(data_filt,
aes(x = tadpole_ID,
y = avg_speed_mm,
fill = tadpole_ID) )+
geom_boxplot(aes(alpha = as.factor(week)), position = position_dodge(width = 0.8)) +
geom_point(aes(group = as.factor(week)),
position = position_dodge(width = 0.8),
alpha = 0.5, size = 1) +
scale_fill_manual(values = rep(c("#3F51B5", "#B7410E"), length.out = 31), guide = "none") +
scale_alpha_manual(
values = c("1" = 1, "2" = 0.75, "3" = 0.5, "4" = 0.25, "5" = 0),
name = "Week",
guide = guide_legend(override.aes = list(fill = "grey40")) # make legend boxes visible
)+
labs(x = "Tadpole ID", y = "Average Speed (mm/sec)", alpha = "Week") +
theme_classic(base_size = 16) +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

#ggsave("Box_average speed.png", width = 14, height = 4.75, dpi = 300)
Average speed when moving
ggplot(data_filt,
aes(x = tadpole_ID,
y = mob_avg_speed_mm,
fill = tadpole_ID) )+
geom_boxplot(aes(alpha = as.factor(week)), position = position_dodge(width = 0.8)) +
geom_point(aes(group = as.factor(week)),
position = position_dodge(width = 0.8),
alpha = 0.5, size = 1) +
scale_fill_manual(values = rep(c("#3F51B5", "#B7410E"), length.out = 31), guide = "none") +
scale_alpha_manual(
values = c("1" = 1, "2" = 0.75, "3" = 0.5, "4" = 0.25, "5" = 0),
name = "Week",
guide = guide_legend(override.aes = list(fill = "grey40")) # make legend boxes visible
)+
labs(x = "Tadpole ID", y = "Average Speed when moving (mm/sec)", alpha = "Week") +
theme_classic(base_size = 16) +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

Proportion time moving
ggplot(data_filt,
aes(x = tadpole_ID,
y = mobility_rate,
fill = tadpole_ID) )+
geom_boxplot(aes(alpha = as.factor(week)), position = position_dodge(width = 0.8)) +
geom_point(aes(group = as.factor(week)),
position = position_dodge(width = 0.8),
alpha = 0.5, size = 1) +
scale_fill_manual(values = rep(c("#3F51B5", "#B7410E"), length.out = 31), guide = "none") +
scale_alpha_manual(
values = c("1" = 1, "2" = 0.75, "3" = 0.5, "4" = 0.25, "5" = 0),
name = "Week",
guide = guide_legend(override.aes = list(fill = "grey40")) # make legend boxes visible
)+
scale_y_continuous(labels = scales::percent) +
labs(x = "Tadpole ID", y = "Proportion time moving (%)", alpha = "Week") +
theme_classic(base_size = 16) +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

Proportion area explored
ggplot(data_filt,
aes(x = tadpole_ID,
y = exploration_rate_explored_div_by_total,
fill = tadpole_ID) )+
geom_boxplot(aes(alpha = as.factor(week)), position = position_dodge(width = 0.8)) +
geom_point(aes(group = as.factor(week)),
position = position_dodge(width = 0.8),
alpha = 0.5, size = 1) +
scale_fill_manual(values = rep(c("#3F51B5", "#B7410E"), length.out = 31), guide = "none") +
scale_alpha_manual(
values = c("1" = 1, "2" = 0.75, "3" = 0.5, "4" = 0.25, "5" = 0),
name = "Week",
guide = guide_legend(override.aes = list(fill = "grey40")) # make legend boxes visible
)+
scale_y_continuous(labels = scales::percent) +
labs(x = "Tadpole ID", y = "Proportion area explored (%)", alpha = "Week") +
theme_classic(base_size = 16) +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

#ggsave("Box_area explored.png", width = 14, height = 4.75, dpi = 300)
Total distance traveled
ggplot(data_filt,
aes(x = tadpole_ID,
y = total_distance_mm,
fill = tadpole_ID) )+
geom_boxplot(aes(alpha = as.factor(week)), position = position_dodge(width = 0.8)) +
geom_point(aes(group = as.factor(week)),
position = position_dodge(width = 0.8),
alpha = 0.5, size = 1) +
scale_fill_manual(values = rep(c("#3F51B5", "#B7410E"), length.out = 31), guide = "none") +
scale_alpha_manual(
values = c("1" = 1, "2" = 0.75, "3" = 0.5, "4" = 0.25, "5" = 0),
name = "Week",
guide = guide_legend(override.aes = list(fill = "grey40")) # make legend boxes visible
)+
labs(x = "Tadpole ID", y = "Total distance traveled (mm)", alpha = "Week") +
theme_classic(base_size = 16) +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
### Total time frozen
ggplot(data_filt,
aes(x = tadpole_ID,
y = total_time_frozen_s,
fill = tadpole_ID) )+
geom_boxplot(aes(alpha = as.factor(week)), position = position_dodge(width = 0.8)) +
geom_point(aes(group = as.factor(week)),
position = position_dodge(width = 0.8),
alpha = 0.5, size = 1) +
scale_fill_manual(values = rep(c("#3F51B5", "#B7410E"), length.out = 31), guide = "none") +
scale_alpha_manual(
values = c("1" = 1, "2" = 0.75, "3" = 0.5, "4" = 0.25, "5" = 0),
name = "Week",
guide = guide_legend(override.aes = list(fill = "grey40")) # make legend boxes visible
)+
labs(x = "Tadpole ID", y = "Total time frozen (sec)", alpha = "Week") +
theme_classic(base_size = 16) +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

Latency to emerge
ggplot(data_filt,
aes(x = tadpole_ID,
y = lat_emerge,
fill = tadpole_ID) )+
geom_boxplot(aes(alpha = as.factor(week)), position = position_dodge(width = 0.8)) +
geom_point(aes(group = as.factor(week)),
position = position_dodge(width = 0.8),
alpha = 0.5, size = 1) +
scale_fill_manual(values = rep(c("#3F51B5", "#B7410E"), length.out = 31), guide = "none") +
scale_alpha_manual(
values = c("1" = 1, "2" = 0.75, "3" = 0.5, "4" = 0.25, "5" = 0),
name = "Week",
guide = guide_legend(override.aes = list(fill = "grey40")) # make legend boxes visible
)+
labs(x = "Tadpole ID", y = "Latency to emerge (sec)", alpha = "Week") +
theme_classic(base_size = 16) +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

Time exposed (out of shelter)
ggplot(data_filt,
aes(x = tadpole_ID,
y = time_uncovered,
fill = tadpole_ID) )+
geom_boxplot(aes(alpha = as.factor(week)), position = position_dodge(width = 0.8)) +
geom_point(aes(group = as.factor(week)),
position = position_dodge(width = 0.8),
alpha = 0.5, size = 1) +
scale_fill_manual(values = rep(c("#3F51B5", "#B7410E"), length.out = 31), guide = "none") +
scale_alpha_manual(
values = c("1" = 1, "2" = 0.75, "3" = 0.5, "4" = 0.25, "5" = 0),
name = "Week",
guide = guide_legend(override.aes = list(fill = "grey40")) # make legend boxes visible
)+
labs(x = "Tadpole ID", y = "Time exposed (sec)", alpha = "Week") +
theme_classic(base_size = 16) +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

Number of Crossovers
ggplot(data_filt,
aes(x = tadpole_ID,
y = num_crossing,
fill = tadpole_ID) )+
geom_boxplot(aes(alpha = as.factor(week)), position = position_dodge(width = 0.8)) +
geom_point(aes(group = as.factor(week)),
position = position_dodge(width = 0.8),
alpha = 0.5, size = 1) +
scale_fill_manual(values = rep(c("#3F51B5", "#B7410E"), length.out = 31), guide = "none") +
scale_alpha_manual(
values = c("1" = 1, "2" = 0.75, "3" = 0.5, "4" = 0.25, "5" = 0),
name = "Week",
guide = guide_legend(override.aes = list(fill = "grey40")) # make legend boxes visible
)+
labs(x = "Tadpole ID", y = "# times crossing boundary", alpha = "Week") +
theme_classic(base_size = 16) +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

Repeatability within each week
make a function to calculate repeatability of each week and combine
to a data frame
rpt_by_wk <- function(data, var) {
data %>%
filter(week %in% 1:5) %>% # note that many don't have wk 5 data
group_by(week) %>%
group_map(~ { #apply to each group
rpt_result <- rpt(
reformulate("1 | tadpole_ID", response = var),
grname = "tadpole_ID",
data = .x,
datatype = "Gaussian",
nboot = 1000,
npermut = 1000)
rpt_summary <- data.frame(week = .y$week, summary(rpt_result)$rpt, row.names = NULL)
return(rpt_summary)
}) %>%
bind_rows()
}
Activity - average speed when moving
rpt_avg_mobspeed <- rpt_by_wk(data_filt, "mob_avg_speed_mm")
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
rpt_avg_mobspeed %>% kable(digits = 3)
| 1 |
0.372 |
0.101 |
0.158 |
0.546 |
0.001 |
1 |
| 2 |
0.564 |
0.098 |
0.334 |
0.719 |
0.001 |
1 |
| 3 |
0.641 |
0.085 |
0.443 |
0.762 |
0.001 |
1 |
| 4 |
0.598 |
0.148 |
0.224 |
0.812 |
0.001 |
1 |
Activity - total distance traveled
rpt_dist <- rpt_by_wk(data_filt, "total_distance_mm")
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
rpt_dist %>% kable(digit = 3)
| 1 |
0.319 |
0.104 |
0.101 |
0.501 |
0.002 |
1 |
| 2 |
0.656 |
0.084 |
0.452 |
0.785 |
0.001 |
1 |
| 3 |
0.697 |
0.077 |
0.521 |
0.821 |
0.001 |
1 |
| 4 |
0.621 |
0.147 |
0.227 |
0.803 |
0.001 |
1 |
Activity - number of crossovers
rpt_cross <- rpt_by_wk(data_filt, "num_crossing")
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
rpt_cross %>% kable(digit = 3)
| 1 |
0.381 |
0.107 |
0.154 |
0.563 |
0.001 |
1 |
| 2 |
0.668 |
0.083 |
0.469 |
0.791 |
0.001 |
1 |
| 3 |
0.716 |
0.076 |
0.536 |
0.825 |
0.001 |
1 |
| 4 |
0.373 |
0.164 |
0.004 |
0.650 |
0.011 |
1 |
Boldness - latency to emerage
rpt_lat_emerge <- rpt_by_wk(data_filt, "lat_emerge")
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
rpt_lat_emerge %>% kable(digits = 3)
| 1 |
0.390 |
0.108 |
0.169 |
0.574 |
0.002 |
1 |
| 2 |
0.108 |
0.088 |
0.000 |
0.308 |
0.120 |
1 |
| 3 |
0.183 |
0.100 |
0.000 |
0.384 |
0.020 |
1 |
| 4 |
0.000 |
0.081 |
0.000 |
0.284 |
1.000 |
1 |
Boldness - Time exposed
rpt_time_uncovered <- rpt_by_wk(data_filt, "time_uncovered")
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
rpt_time_uncovered %>% kable(digits = 3)
| 1 |
0.487 |
0.103 |
0.251 |
0.653 |
0.001 |
1 |
| 2 |
0.414 |
0.103 |
0.197 |
0.589 |
0.001 |
1 |
| 3 |
0.173 |
0.097 |
0.000 |
0.354 |
0.036 |
1 |
| 4 |
0.175 |
0.141 |
0.000 |
0.470 |
0.081 |
1 |
Exploration - area explored
rpt_exploration_prop <- rpt_by_wk(data_filt, "exploration_rate_explored_div_by_total")
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
rpt_exploration_prop %>% kable(digit = 3)
| 1 |
0.420 |
0.103 |
0.210 |
0.599 |
0.001 |
0 |
| 2 |
0.606 |
0.090 |
0.392 |
0.749 |
0.001 |
0 |
| 3 |
0.779 |
0.063 |
0.628 |
0.874 |
0.001 |
0 |
| 4 |
0.640 |
0.137 |
0.283 |
0.822 |
0.001 |
0 |
Repeatability across development
make function for doing repeatability analysis of different variables
together
rpt_multi_vars <- function(data, vars) {
vars %>%
purrr::map_df(~ { #map + row binding
rpt_result <- rpt(
reformulate("1 | tadpole_ID", response = .x),
grname = "tadpole_ID",
data = data,
datatype = "Gaussian",
nboot = 1000,
npermut = 1000
)
rpt_summary <- data.frame(variable = .x,
summary(rpt_result)$rpt,
row.names = NULL)
return(rpt_summary)
})
}
Repeatability across all assays
rpt_overall_summary <- rpt_multi_vars(data_filt,
c("mob_avg_speed_mm", "total_distance_mm","num_crossing", #activity variables
"exploration_rate_explored_div_by_total", #exploration variable
"lat_emerge", "time_uncovered" #boldness variables
)
)
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
rpt_overall_summary %>% kable(digit = 3)
| mob_avg_speed_mm |
0.232 |
0.063 |
0.110 |
0.362 |
0.001 |
0.000 |
| total_distance_mm |
0.219 |
0.061 |
0.106 |
0.335 |
0.001 |
0.000 |
| num_crossing |
0.124 |
0.049 |
0.041 |
0.226 |
0.001 |
0.000 |
| exploration_rate_explored_div_by_total |
0.233 |
0.062 |
0.109 |
0.357 |
0.001 |
0.000 |
| lat_emerge |
0.047 |
0.031 |
0.000 |
0.110 |
0.022 |
0.044 |
| time_uncovered |
0.112 |
0.045 |
0.030 |
0.202 |
0.001 |
0.000 |
Repeatability of weekly averages
rpt_wk_avg_summary <- rpt_multi_vars(data_wk_avg_filt,
c("mob_avg_speed_mm", "total_distance_mm","num_crossing", #activity variables
"exploration_rate_explored_div_by_total", #exploration variable
"lat_emerge", "time_uncovered" #boldness variables
)
)
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
rpt_wk_avg_summary %>% kable(digit = 3)
| mob_avg_speed_mm |
0.180 |
0.104 |
0 |
0.397 |
0.031 |
0.046 |
| total_distance_mm |
0.171 |
0.107 |
0 |
0.396 |
0.038 |
0.046 |
| num_crossing |
0.000 |
0.056 |
0 |
0.188 |
1.000 |
0.500 |
| exploration_rate_explored_div_by_total |
0.117 |
0.095 |
0 |
0.316 |
0.101 |
0.137 |
| lat_emerge |
0.000 |
0.057 |
0 |
0.183 |
1.000 |
1.000 |
| time_uncovered |
0.051 |
0.078 |
0 |
0.249 |
0.295 |
0.329 |
Developmental changes in personality
Figure: averages by week
Color codes: activity blue, exploration green , boldness coral
fig_avg_speed_mov <-
data_wk_avg_filt %>%
filter(week %in% 1:5) %>%
ggplot(aes(x = week, y = mob_avg_speed_mm, group = tadpole_ID)) +
geom_line(color = "grey80", size = 1, alpha = 0.8) +
stat_summary(aes(group = 1), fun = mean, geom = "line", color = "#0072B2", size = 1.5) +
stat_summary(aes(group = 1), fun = mean, geom = "point", color = "#0072B2", size = 4) +
stat_summary(aes(group = 1), fun.data = mean_se, geom = "errorbar", color = "#0072B2", width = 0.2, size = 1.5) +
labs(x = "Week", y = "Average Speed when \n moving (mm/s)") +
theme_classic(base_size = 16)
fig_dist <-
data_wk_avg_filt %>%
filter(week %in% 1:5) %>%
ggplot(aes(x = week, y = total_distance_mm, group = tadpole_ID)) +
geom_line(color = "grey80", size = 1, alpha = 0.8) +
stat_summary(aes(group = 1), fun = mean, geom = "line", color = "#0072B2", size = 1.5) +
stat_summary(aes(group = 1), fun = mean, geom = "point", color = "#0072B2", size = 4) +
stat_summary(aes(group = 1), fun.data = mean_se, geom = "errorbar", color = "#0072B2", width = 0.2, size = 1.5) +
labs(x = "Week", y = "Total distance \n traveled (mm)") +
theme_classic(base_size = 16)
fig_crossing <-
data_wk_avg_filt %>%
filter(week %in% 1:5) %>%
ggplot(aes(x = week, y = num_crossing, group = tadpole_ID)) +
geom_line(color = "grey80", size = 1, alpha = 0.8) +
stat_summary(aes(group = 1), fun = mean, geom = "line", color = "#0072B2", size = 1.5) +
stat_summary(aes(group = 1), fun = mean, geom = "point", color = "#0072B2", size = 4) +
stat_summary(aes(group = 1), fun.data = mean_se, geom = "errorbar", color = "#0072B2", width = 0.2, size = 1.5) +
labs(x = "Week", y = "Number of \n crossovers") +
theme_classic(base_size = 16)
fig_area_explored <-
data_wk_avg_filt %>%
filter(week %in% 1:5) %>%
ggplot(aes(x = week, y = exploration_rate_explored_div_by_total, group = tadpole_ID)) +
geom_line(color = "grey80", size = 1, alpha = 0.8) +
stat_summary(aes(group = 1), fun = mean, geom = "line", color = "palegreen4", size = 1.5) +
stat_summary(aes(group = 1), fun = mean, geom = "point", color = "palegreen4", size = 4) +
stat_summary(aes(group = 1), fun.data = mean_se, geom = "errorbar", color = "palegreen4", width = 0.2, size = 1.5) +
labs(x = "Week", y = "Proportion area \n explored (%)") +
scale_y_continuous(labels = scales::percent) +
theme_classic(base_size = 16)
fig_lat_emerge <-
data_wk_avg_filt %>%
filter(week %in% 1:5) %>%
ggplot(aes(x = as.factor(week), y = lat_emerge, group = tadpole_ID)) +
geom_line(color = "grey80", size = 1, alpha = 0.8) +
stat_summary(aes(group = 1), fun = mean, geom = "line", color = "coral2", size = 1.5) +
stat_summary(aes(group = 1), fun = mean, geom = "point", color = "coral2", size = 4) +
stat_summary(aes(group = 1), fun.data = mean_se, geom = "errorbar", color = "coral2", width = 0.2, size = 1.5) +
labs(x = "Week", y = "Latency to \n emerge (s)") +
theme_classic(base_size = 16)
fig_time_uncovered <-
data_wk_avg_filt %>%
filter(week %in% 1:5) %>%
ggplot(aes(x = week, y = time_uncovered, group = tadpole_ID)) +
geom_line(color = "grey80", size = 1, alpha = 0.8) +
stat_summary(aes(group = 1), fun = mean, geom = "line", color = "coral2", size = 1.5) +
stat_summary(aes(group = 1), fun = mean, geom = "point", color = "coral2", size = 4) +
stat_summary(aes(group = 1), fun.data = mean_se, geom = "errorbar", color = "coral2", width = 0.2, size = 1.5) +
labs(x = "Week", y = "Time exposed (s)") +
theme_classic(base_size = 16)
egg::ggarrange(fig_avg_speed_mov,fig_dist, fig_crossing, fig_area_explored, fig_lat_emerge, fig_time_uncovered,
nrow = 6)

Activity: average speed when moving
mod <- lmer(mob_avg_speed_mm ~ week + (1 | tadpole_ID), data = data_filt)
summary(mod)$coefficients %>% kable(digits = 3)
| (Intercept) |
13.148 |
0.716 |
18.351 |
| week |
-1.901 |
0.217 |
-8.765 |
Anova(mod) %>% kable(digits = 3)
Activity: total distance traveled
mod <- lmer(total_distance_mm ~ week + (1 | tadpole_ID), data = data_filt)
summary(mod)$coefficients %>% kable(digits = 3)
| (Intercept) |
5489.570 |
357.192 |
15.369 |
| week |
-985.764 |
109.769 |
-8.980 |
Anova(mod) %>% kable(digits = 3)
Activity: number of crossovers
mod <- lmer(num_crossing ~ week + (1 | tadpole_ID), data = data_filt)
summary(mod)$coefficients %>% kable(digits = 3)
| (Intercept) |
21.242 |
1.252 |
16.967 |
| week |
-5.952 |
0.382 |
-15.570 |
Anova(mod) %>% kable(digits = 3)
Exploration: total area explored
mod <- lmer(exploration_rate_explored_div_by_total ~ week + (1 | tadpole_ID), data = data)
summary(mod)$coefficients %>% kable(digits = 3)
| (Intercept) |
0.687 |
0.034 |
19.951 |
| week |
-0.095 |
0.005 |
-18.247 |
Anova(mod) %>% kable(digits = 3)
Boldness: latency to emerge
Technically I should use a Cox model instead of lmer…
mod <- lmer(lat_emerge ~ week + (1 | tadpole_ID), data = data_filt)
summary(mod)$coefficients %>% kable(digits = 3)
| (Intercept) |
68.748 |
20.906 |
3.288 |
| week |
26.588 |
7.935 |
3.351 |
Anova(mod) %>% kable(digits = 3)
Boldness: time exposed
mod <- lmer(time_uncovered ~ week + (1 | tadpole_ID), data = data_filt)
summary(mod)$coefficients %>% kable(digits = 3)
| (Intercept) |
226.712 |
14.518 |
15.616 |
| week |
-45.952 |
4.906 |
-9.367 |
Anova(mod) %>% kable(digits = 3)
Sequence effect
Figure: by trial sequence
fig_avg_speed_mov_seq<-
ggplot(data_filt, aes(x = trial_seq, y = mob_avg_speed_mm, group = tadpole_ID)) +
geom_line(color = "grey80", size = 1, alpha = 0.8) +
stat_summary(aes(group = 1), fun = mean, geom = "line", color = "#0072B2", size = 1.5) +
stat_summary(aes(group = 1), fun = mean, geom = "point", color = "#0072B2", size = 2.5) +
stat_summary(aes(group = 1), fun.data = mean_se, geom = "errorbar", color = "#0072B2", width = 0.2) +
labs(x = "Trial number", y = "Average Speed when \n moving (mm/s)") +
theme_classic(base_size = 15)
fig_dist_seq <-
ggplot(data_filt, aes(x = trial_seq, y = total_distance_mm, group = tadpole_ID)) +
geom_line(color = "grey80", size = 1, alpha = 0.8) +
stat_summary(aes(group = 1), fun = mean, geom = "line", color = "#0072B2", size = 1.5) +
stat_summary(aes(group = 1), fun = mean, geom = "point", color = "#0072B2", size = 4) +
stat_summary(aes(group = 1), fun.data = mean_se, geom = "errorbar", color = "#0072B2", width = 0.2, size = 1.5) +
labs(x = "Trial number", y = "Total distance \n traveled (mm)") +
theme_classic(base_size = 16)
fig_crossing_seq <-
ggplot(data_filt, aes(x = trial_seq, y = num_crossing, group = tadpole_ID)) +
geom_line(color = "grey80", size = 1, alpha = 0.8) +
stat_summary(aes(group = 1), fun = mean, geom = "line", color = "#0072B2", size = 1.5) +
stat_summary(aes(group = 1), fun = mean, geom = "point", color = "#0072B2", size = 4) +
stat_summary(aes(group = 1), fun.data = mean_se, geom = "errorbar", color = "#0072B2", width = 0.2, size = 1.5) +
labs(x = "Trial number", y = "Number of \n crossovers") +
theme_classic(base_size = 16)
fig_area_explored_seq <-
ggplot(data_filt, aes(x = trial_seq, y = exploration_rate_explored_div_by_total, group = tadpole_ID)) +
geom_line(color = "grey80", size = 1, alpha = 0.8) +
stat_summary(aes(group = 1), fun = mean, geom = "line", color = "palegreen4", size = 1.5) +
stat_summary(aes(group = 1), fun = mean, geom = "point", color = "palegreen4", size = 4) +
stat_summary(aes(group = 1), fun.data = mean_se, geom = "errorbar", color = "palegreen4", width = 0.2, size = 1.5) +
labs(x = "Trial number", y = "Proportion area \n explored (%)") +
scale_y_continuous(labels = scales::percent) +
theme_classic(base_size = 16)
fig_lat_emerge_seq <-
ggplot(data_filt, aes(x = trial_seq, y = lat_emerge, group = tadpole_ID)) +
geom_line(color = "grey80", size = 1, alpha = 0.8) +
stat_summary(aes(group = 1), fun = mean, geom = "line", color = "coral2", size = 1.5) +
stat_summary(aes(group = 1), fun = mean, geom = "point", color = "coral2", size = 4) +
stat_summary(aes(group = 1), fun.data = mean_se, geom = "errorbar", color = "coral2", width = 0.2, size = 1.5) +
labs(x = "Trial number", y = "Latency to \n emerge (s)") +
theme_classic(base_size = 16)
fig_time_uncovered_seq <-
ggplot(data_filt, aes(x = trial_seq, y = time_uncovered, group = tadpole_ID)) +
geom_line(color = "grey80", size = 1, alpha = 0.8) +
stat_summary(aes(group = 1), fun = mean, geom = "line", color = "coral2", size = 1.5) +
stat_summary(aes(group = 1), fun = mean, geom = "point", color = "coral2", size = 4) +
stat_summary(aes(group = 1), fun.data = mean_se, geom = "errorbar", color = "coral2", width = 0.2, size = 1.5) +
labs(x = "Trial number", y = "Time exposed (s))") +
theme_classic(base_size = 16)
egg::ggarrange(fig_avg_speed_mov_seq,fig_dist_seq, fig_crossing_seq, fig_area_explored_seq, fig_lat_emerge_seq, fig_time_uncovered_seq,
nrow = 6)
### Stats: TBD
Behavioral Syndrome
Principle Component Analysis
#pca in this package seems to not be able to handle na
#prep dataset without NA, but with labels for adding back later
data_pca <- data_filt %>%
mutate(row_num = row_number()) %>% #for later to reliably add PC values back
select(row_num,
mob_avg_speed_mm,
total_distance_mm,
num_crossing,
exploration_rate_explored_div_by_total,
lat_emerge,
time_uncovered) %>%
drop_na()
#PCA
pca <- data_pca %>%
select(-row_num) %>%
prcomp(scale. = TRUE)
#extract PC1-3
pca_scores <- as.data.frame(pca$x) %>%
mutate(row_num = data_pca$row_num) %>%
select(row_num, PC1, PC2, PC3)
#Add back to original dataset
data_filt <- data_filt %>%
mutate(row_num = row_number()) %>%
left_join(pca_scores, by = "row_num") %>%
select(-row_num) # Clean up the matching row numbers
Variance explained:
summary(pca)
## Importance of components:
## PC1 PC2 PC3 PC4 PC5 PC6
## Standard deviation 1.8361 1.0443 0.8851 0.62967 0.53752 0.26303
## Proportion of Variance 0.5619 0.1818 0.1306 0.06608 0.04815 0.01153
## Cumulative Proportion 0.5619 0.7437 0.8742 0.94031 0.98847 1.00000
Loadings:
pca$rotation %>% kable (digits = 3)
| mob_avg_speed_mm |
-0.481 |
0.330 |
-0.223 |
0.016 |
-0.292 |
0.724 |
| total_distance_mm |
-0.490 |
0.237 |
-0.229 |
-0.047 |
-0.434 |
-0.679 |
| num_crossing |
-0.414 |
-0.320 |
0.265 |
-0.790 |
0.177 |
0.040 |
| exploration_rate_explored_div_by_total |
-0.465 |
0.213 |
-0.038 |
0.316 |
0.791 |
-0.106 |
| lat_emerge |
0.154 |
0.740 |
0.629 |
-0.175 |
-0.015 |
-0.044 |
| time_uncovered |
-0.342 |
-0.373 |
0.657 |
0.493 |
-0.262 |
0.029 |
Interpretation: larger PC1 means less active, larger PC2 means more
shy
not the most intuitive, but ok for now I guess; could flip sign when
graphing
Figure: average by week
redo the week dataset (dumb but I’m tired)
data_wk_avg_filt <- data_filt %>%
group_by(tadpole_ID, week) %>%
summarise(avg_speed_mm = mean(avg_speed_mm, na.rm = TRUE),
mob_avg_speed_mm = mean(mob_avg_speed_mm, na.rm = TRUE),
mobility_rate = mean(mobility_rate, na.rm = TRUE),
exploration_rate_explored_div_by_total = mean(exploration_rate_explored_div_by_total, na.rm = TRUE),
total_distance_mm = mean(total_distance_mm, na.rm = TRUE),
total_time_frozen_s = mean(total_time_frozen_s, na.rm = TRUE),
lat_emerge = mean(lat_emerge, na.rm = TRUE),
time_uncovered = mean(time_uncovered, na.rm = TRUE),
num_crossing = mean(num_crossing, na.rm = TRUE),
PC1 = mean(PC1, na.rm = TRUE),
PC2 = mean(PC2, na.rm = TRUE),
PC3 = mean(PC3, na.rm = TRUE),
.groups = "drop" #ungroup after summarise
)
data_wk_avg_filt %>%
ggplot(aes(x = week, y = -PC1, group = tadpole_ID)) +
geom_line(color = "grey80", size = 1, alpha = 0.8) +
stat_summary(aes(group = 1), fun = mean, geom = "line", color = "#0072B2", size = 1.5) +
stat_summary(aes(group = 1), fun = mean, geom = "point", color = "#0072B2", size = 4) +
stat_summary(aes(group = 1), fun.data = mean_se, geom = "errorbar", color = "#0072B2", width = 0.2, size = 1.5) +
labs(x = "Week", y = "PC1: Activity (56.2%)") +
theme_classic(base_size = 16)

data_wk_avg_filt %>%
ggplot(aes(x = week, y = -PC2, group = tadpole_ID)) +
geom_line(color = "grey80", size = 1, alpha = 0.8) +
stat_summary(aes(group = 1), fun = mean, geom = "line", color = "coral2", size = 1.5) +
stat_summary(aes(group = 1), fun = mean, geom = "point", color = "coral2", size = 4) +
stat_summary(aes(group = 1), fun.data = mean_se, geom = "errorbar", color = "coral2", width = 0.2, size = 1.5) +
labs(x = "Week", y = "PC2: Boldness (18.2%)") +
theme_classic(base_size = 16)
