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(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_openfield_071825.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"), as.factor) %>%
mutate_at(c("found_date","testing_date"), lubridate::mdy) %>%
mutate_at(c("total_time_frozen_hh_mm_ss", "invisible_time_hh_mm_ss"),lubridate::hms) %>%
#derive variables
mutate(condition = body_width_mm/length_without_tail_mm,
frozen_sec = as.numeric(total_time_frozen_hh_mm_ss),
invisible_sec = as.numeric(invisible_time_hh_mm_ss),
age = testing_date - found_date) %>%
#add trial sequence per tadpole
arrange(tadpole_ID, week, replicate) %>%
group_by(tadpole_ID) %>%
mutate(trial_seq = row_number()) %>%
ungroup()
Make a dataset with individual averages by week
data_wk_avg <- data %>%
group_by(tadpole_ID, week) %>%
summarise(avg_speed_mm = mean(avg_speed_mm),
mob_avg_speed_mm = mean(mob_avg_speed_mm),
mobility_rate = mean(mobility_rate),
exploration_rate_explored_div_by_total = mean(exploration_rate_explored_div_by_total),
total_distance_mm = mean(total_distance_mm)
)
Data spread:
data %>% select(tadpole_ID, week) %>% table
## week
## tadpole_ID 1 2 3 4 5 6 7
## T5 4 4 4 4 4 0 0
## T6 4 4 4 4 4 0 0
## T7 4 4 4 4 4 0 0
## T8 4 4 4 4 4 4 4
## T9 4 4 4 4 4 0 0
## T10 4 4 4 4 0 0 0
## T11 4 4 4 4 0 0 0
## T12 4 4 4 4 0 0 0
## T13 4 4 4 4 0 0 0
## T14 4 4 4 4 0 0 0
## T15 4 4 4 4 0 0 0
## T16 4 4 4 4 0 0 0
## T17 4 4 0 0 0 0 0
data %>% select(tadpole_ID, gosner_stage) %>% table
## gosner_stage
## tadpole_ID 26 30 31 36 37 41 42 46
## T5 3 16 0 0 0 0 0 0
## T6 3 0 0 4 0 2 2 8
## T7 4 4 0 0 0 4 4 4
## T8 8 16 4 0 0 0 0 0
## T9 4 4 0 0 0 4 4 4
## T10 0 4 2 0 2 4 0 4
## T11 0 8 2 0 0 2 4 0
## T12 0 6 2 0 2 0 6 0
## T13 0 16 0 0 0 0 0 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 0 0 0
Comprehensive boxplots
Average speed
ggplot(data,
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 = hcl.colors(13, palette = "Dark3"), guide = "none") +
scale_alpha_manual(
values = c("1" = 1, "2" = 0.8, "3" = 0.6, "4" = 0.4, "5" = 0.2, "6" = 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 = 20) +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

Average speed when moving
ggplot(data,
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 = hcl.colors(13, palette = "Dark3"), guide = "none") +
scale_alpha_manual(
values = c("1" = 1, "2" = 0.8, "3" = 0.6, "4" = 0.4, "5" = 0.2, "6" = 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 = 20) +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

Proportion time moving
ggplot(data,
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 = hcl.colors(13, palette = "Dark3"), guide = "none") +
scale_alpha_manual(
values = c("1" = 1, "2" = 0.8, "3" = 0.6, "4" = 0.4, "5" = 0.2, "6" = 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 = 20) +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

Proportion area explored
ggplot(data,
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 = hcl.colors(13, palette = "Dark3"), guide = "none") +
scale_alpha_manual(
values = c("1" = 1, "2" = 0.8, "3" = 0.6, "4" = 0.4, "5" = 0.2, "6" = 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 = 20) +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

Total distance traveled
ggplot(data,
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 = hcl.colors(13, palette = "Dark3"), guide = "none") +
scale_alpha_manual(
values = c("1" = 1, "2" = 0.8, "3" = 0.6, "4" = 0.4, "5" = 0.2, "6" = 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 = 20) +
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) %>%
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()
}
Average speed
rpt_avg_speed <- rpt_by_wk(data, "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 :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
rpt_avg_speed %>% kable(digit = 3)
| 1 |
0.324 |
0.163 |
0.000 |
0.608 |
0.024 |
1 |
| 2 |
0.499 |
0.156 |
0.121 |
0.727 |
0.001 |
1 |
| 3 |
0.675 |
0.132 |
0.318 |
0.838 |
0.001 |
1 |
| 4 |
0.940 |
0.039 |
0.819 |
0.974 |
0.001 |
1 |
| 5 |
0.949 |
0.092 |
0.652 |
0.985 |
0.001 |
1 |
Average speed when moving
rpt_avg_mobspeed <- rpt_by_wk(data, "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 :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
rpt_avg_mobspeed %>% kable(digit = 3)
| 1 |
0.507 |
0.158 |
0.122 |
0.721 |
0.001 |
1 |
| 2 |
0.427 |
0.160 |
0.079 |
0.676 |
0.002 |
1 |
| 3 |
0.485 |
0.153 |
0.126 |
0.713 |
0.001 |
1 |
| 4 |
0.883 |
0.067 |
0.698 |
0.943 |
0.001 |
1 |
| 5 |
0.905 |
0.143 |
0.429 |
0.973 |
0.001 |
1 |
Proportion time moving
rpt_avg_mobprop <- rpt_by_wk(data, "mobility_rate")
## 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_avg_mobprop %>% kable(digit = 3)
| 1 |
0.647 |
0.138 |
0.298 |
0.824 |
0.001 |
0 |
| 2 |
0.542 |
0.152 |
0.161 |
0.760 |
0.001 |
0 |
| 3 |
0.861 |
0.070 |
0.675 |
0.935 |
0.001 |
0 |
| 4 |
0.807 |
0.100 |
0.527 |
0.912 |
0.001 |
0 |
| 5 |
0.792 |
0.197 |
0.173 |
0.937 |
0.001 |
0 |
Proportion area explored
rpt_exploration_prop <- rpt_by_wk(data, "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 :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
rpt_exploration_prop %>% kable(digit = 3)
| 1 |
0.829 |
0.094 |
0.540 |
0.922 |
0.001 |
0.000 |
| 2 |
0.384 |
0.163 |
0.013 |
0.660 |
0.005 |
0.000 |
| 3 |
0.551 |
0.154 |
0.185 |
0.755 |
0.001 |
0.017 |
| 4 |
0.833 |
0.088 |
0.587 |
0.933 |
0.001 |
0.000 |
| 5 |
0.959 |
0.081 |
0.738 |
0.988 |
0.001 |
0.000 |
Total distance traveled
rpt_dist <- rpt_by_wk(data, "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 :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
rpt_dist %>% kable(digit = 3)
| 1 |
0.322 |
0.162 |
0.000 |
0.602 |
0.012 |
1 |
| 2 |
0.501 |
0.159 |
0.118 |
0.742 |
0.001 |
1 |
| 3 |
0.679 |
0.125 |
0.350 |
0.836 |
0.001 |
1 |
| 4 |
0.939 |
0.039 |
0.827 |
0.975 |
0.001 |
1 |
| 5 |
0.945 |
0.085 |
0.672 |
0.986 |
0.001 |
1 |
Repeatability across development
make function for repeatability of different variables
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)
})
}
Analysis: overall repeatability
rpt_overall_summary <- rpt_multi_vars(data, c("avg_speed_mm", "mob_avg_speed_mm","mobility_rate","exploration_rate_explored_div_by_total","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 :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
rpt_overall_summary %>% kable(digit = 3)
| avg_speed_mm |
0.349 |
0.101 |
0.144 |
0.529 |
0.001 |
0 |
| mob_avg_speed_mm |
0.315 |
0.102 |
0.112 |
0.496 |
0.001 |
0 |
| mobility_rate |
0.334 |
0.102 |
0.124 |
0.525 |
0.001 |
0 |
| exploration_rate_explored_div_by_total |
0.305 |
0.102 |
0.116 |
0.494 |
0.001 |
0 |
| total_distance_mm |
0.348 |
0.102 |
0.136 |
0.543 |
0.001 |
0 |
Analysis: week averages
rpt_wk_avg_summary <- rpt_multi_vars(data_wk_avg, c("avg_speed_mm", "mob_avg_speed_mm","mobility_rate","exploration_rate_explored_div_by_total","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 :
## Bootstrap Progress:
## Permutation Progress for tadpole_ID :
rpt_wk_avg_summary %>% kable(digit = 3)
| avg_speed_mm |
0.380 |
0.157 |
0.037 |
0.654 |
0.003 |
0.003 |
| mob_avg_speed_mm |
0.319 |
0.154 |
0.000 |
0.590 |
0.005 |
0.010 |
| mobility_rate |
0.278 |
0.145 |
0.000 |
0.539 |
0.011 |
0.020 |
| exploration_rate_explored_div_by_total |
0.219 |
0.144 |
0.000 |
0.519 |
0.044 |
0.045 |
| total_distance_mm |
0.380 |
0.159 |
0.028 |
0.652 |
0.004 |
0.003 |
Figure: Spaghetti plots
fig_spg_speed <-
ggplot(data_wk_avg,
aes(x = week, y = avg_speed_mm, group = tadpole_ID, color = tadpole_ID)) +
geom_line(alpha = 0.9, size = 1) +
labs(x = "Week", y = "Average Speed (mm/sec)") +
scale_color_manual(values = hcl.colors(15, palette = "Mako"),
name = "tadpole_ID") +
theme_classic(base_size = 15)
fig_spg_speed_mov <-
ggplot(data_wk_avg,
aes(x = week, y = mob_avg_speed_mm, group = tadpole_ID, color = tadpole_ID)) +
geom_line(alpha = 0.9, size = 1) +
labs(x = "Week", y = "Average Speed when moving (mm/sec)") +
scale_color_manual(values = hcl.colors(15, palette = "Mako"),
guide = "none") +
theme(legend.position = "none") +
theme_classic(base_size = 15)
fig_spg_mob_rate <-
ggplot(data_wk_avg,
aes(x = week, y = mobility_rate, group = tadpole_ID, color = tadpole_ID)) +
geom_line(alpha = 0.9, size = 1) +
labs(x = "Week", y = "Proportion time moving (%)") +
scale_color_manual(values = hcl.colors(15, palette = "Mako"),
guide = "none") +
scale_y_continuous(labels = scales::percent) +
theme(legend.position = "none") +
theme_classic(base_size = 15)
fig_spg_area_explored <-
ggplot(data_wk_avg,
aes(x = week, y = exploration_rate_explored_div_by_total, group = tadpole_ID, color = tadpole_ID)) +
geom_line(alpha = 0.9, size = 1) +
labs(x = "Week", y = "Proportion area explored (%)") +
scale_color_manual(values = hcl.colors(15, palette = "Mako"),
guide = "none") +
scale_y_continuous(labels = scales::percent) +
theme(legend.position = "none") +
theme_classic(base_size = 15)
fig_spg_dist <-
ggplot(data_wk_avg,
aes(x = week, y = total_distance_mm, group = tadpole_ID, color = tadpole_ID)) +
geom_line(alpha = 0.9, size = 1) +
labs(x = "Week", y = "Total distance traveled (mm)") +
scale_color_manual(values = hcl.colors(15, palette = "Mako"),
guide = "none") +
theme(legend.position = "none") +
theme_classic(base_size = 15)
egg::ggarrange(fig_spg_speed, fig_spg_speed_mov, fig_spg_mob_rate, fig_spg_area_explored, fig_spg_dist,
nrow = 5)

Figure: averages
fig_avg_speed <-
data_wk_avg %>%
filter(week %in% 1:5) %>%
ggplot(aes(x = as.factor(week), y = 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 = "Week", y = "Average Speed (mm/sec)") +
theme_classic(base_size = 15)
fig_avg_speed_mov <-
data_wk_avg %>%
filter(week %in% 1:5) %>%
ggplot(aes(x = as.factor(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 = 2.5) +
stat_summary(aes(group = 1), fun.data = mean_se, geom = "errorbar", color = "#0072B2", width = 0.2) +
labs(x = "Week", y = "Average Speed when moving (mm/sec)") +
theme_classic(base_size = 15)
fig_avg_mob_rate <-
data_wk_avg %>%
filter(week %in% 1:5) %>%
ggplot(aes(x = as.factor(week), y = mobility_rate, 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 = "Week", y = "Proportion time moving (%)") +
scale_y_continuous(labels = scales::percent) +
theme_classic(base_size = 15)
fig_avg_area_explored <-
data_wk_avg %>%
filter(week %in% 1:5) %>%
ggplot(aes(x = as.factor(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 = "#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 = "Week", y = "Proportion area explored (%)") +
scale_y_continuous(labels = scales::percent) +
theme_classic(base_size = 15)
fig_avg_dist <-
data_wk_avg %>%
filter(week %in% 1:5) %>%
ggplot(aes(x = as.factor(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 = 2.5) +
stat_summary(aes(group = 1), fun.data = mean_se, geom = "errorbar", color = "#0072B2", width = 0.2) +
labs(x = "Week", y = "Total distance traveled (mm)") +
theme_classic(base_size = 15)
egg::ggarrange(fig_avg_speed, fig_avg_speed_mov, fig_avg_mob_rate, fig_avg_area_explored, fig_avg_dist,
nrow = 5)

Just the two parameters used in the poster
egg::ggarrange(fig_avg_speed, fig_avg_area_explored,
nrow = 2)
