Rensch’s Rule in Costa Rican hummingbirds
University of Costa Rica

Author
Published

November 12, 2025

Source code, data and version control of the project found at https://github.com/maRce10/renschs_rule_costa_rican_hummingbirds

 

Purpose

  • Explore sexual size dimorphism in hummingbird species from Costa Rica

  • Evaluate Rensch’s Rule

 

Report overview

 

1 Explore data

Code
# read data
dat <- as.data.frame(read_excel("./data/raw/supplementary data.xlsx"))

dat$Clade[dat$Clade == "Billiants"] <- "Brilliants"

# read trees
trees <- read.tree("./data/raw/Posterior trees fixed names 339 species 1 swift.trees")

dat$`scientific name`[dat$`scientific name` == "Phaetornis guy"] <- "Phaethornis guy"
dat$`scientific name`[dat$`scientific name` == "Phaetornis longirostris"] <- "Phaethornis longirostris"
dat$`scientific name`[dat$`scientific name` == "Heliomaster longisrostris"] <- "Heliomaster longirostris"
dat$scientific_name <- gsub(" ", "_", dat$`scientific name`)

trees <- lapply(trees, function(tree) {
    tree$tip.label[tree$tip.label == "Amazilia_amabilis"] <- "Polyerata_amabilis"
    tree$tip.label[tree$tip.label == "Hylocharis_eliciae"] <- "Chlorestes_eliciae"
    tree$tip.label[tree$tip.label == "Chlorostilbon_canivetii"] <- "Cynanthus_canivetii"
    tree$tip.label[tree$tip.label == "Elvira_cupreiceps"] <- "Microchera_cupreiceps"
    tree$tip.label[tree$tip.label == "Calliphlox_bryantae"] <- "Philodice_bryantae"
    tree$tip.label[tree$tip.label == "Amazilia_edward"] <- "Saucerottia_edward"
    tree$tip.label[tree$tip.label == "Amazilia_saucerottei"] <- "Saucerottia_hoffmanni"
    tree$tip.label[tree$tip.label == "Amazilia_saucerottei"] <- "Saucerottia_hoffmanni"
    tree$tip.label[tree$tip.label == "Amazilia_candida"] <- "Chlorestes_candida"
    tree$tip.label[tree$tip.label == "Elvira_chionura"] <- "Microchera_chonura"

    subtree <- drop.tip(phy = tree, tip = setdiff(tree$tip.label,
        unique(dat$scientific_name)))

    return(tree)
})


names(dat) <- gsub(" ", ".", names(dat))

# maximum clade credibility consensus tree
mcd_tree <- phangorn::maxCladeCred(trees)

mcd_tree$tip.label <- gsub("_", " ", mcd_tree$tip.label)

ggtree(mcd_tree, layout = "circular", col = viridis(10)[7]) + geom_tiplab(size = 2) +
    theme(plot.margin = unit(c(30, 10, 30, 10), "mm"))

Code
# add log 10 variables
dat$lg10.female.weight <- log10(dat$female.weight)
dat$lg10.male.weight <- log10(dat$male.weight)

2 Run statistical models

Code
prior <- c(prior(normal(0, 10), "b"), prior(normal(0, 50), "Intercept"),
    prior(student_t(3, 0, 20), "sd"), prior(student_t(3, 0, 20), "sigma"))

iter <- 10000

chains <- 1

cores <- 1

2.1 Size comparison among sexes

2.1.1 log(females) ~ log(males)

(note that in the data supplied ln.SEX.weight variables are in natural log)

Code
male_x_mod <- phylogenetic_uncertainty(ln.female.weight ~ ln.male.weight,
    data = dat, sp.id.column = "scientific_name", phylos = trees,
    family = gaussian(), prior = prior, iter = iter, control = list(adapt_delta = 0.99,
        max_treedepth = 15), fit.name = "male_vs_female_size", save.fits = FALSE,
    save.combined = TRUE, path = "./data/processed/", chains = chains,
    cores = cores)
Code
brmsish::extended_summary(read.file = "./data/processed/male_vs_female_size_1000_iterations.rds",
    highlight = TRUE)

2.2 male_vs_female_size_1000_iterations

formula family priors iterations chains thinning warmup diverg_transitions rhats > 1.05 min_bulk_ESS min_tail_ESS seed
1 ln.female.weight ~ ln.male.weight + (1 | gr(scientific_name, cov = vcv.phylo)) gaussian (identity) b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) 1000 100 1 500 1 (2e-05%) 0 25587.67 25143.11 1984988351
Estimate l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
b_Intercept 0.198 0.038 0.369 1.003 25587.67 25143.11
b_ln.male.weight 0.838 0.780 0.896 1.001 39303.85 36999.33

2.2.1 log10(females) ~ log10(males)

Code
log10_male_x_mod <- phylogenetic_uncertainty(lg10.female.weight ~
    lg10.male.weight, data = dat, sp.id.column = "scientific_name",
    phylos = trees, family = gaussian(), prior = prior, iter = iter,
    control = list(adapt_delta = 0.99, max_treedepth = 15), fit.name = "log10_male_vs_female_size",
    save.fits = FALSE, save.combined = TRUE, path = "./data/processed/",
    chains = chains, cores = cores)
Code
brmsish::extended_summary(read.file = "./data/processed/log10_male_vs_female_size_1000_iterations.rds",
    highlight = TRUE)

2.3 log10_male_vs_female_size_1000_iterations

formula family priors iterations chains thinning warmup diverg_transitions rhats > 1.05 min_bulk_ESS min_tail_ESS seed
1 lg10.female.weight ~ lg10.male.weight + (1 | gr(scientific_name, cov = vcv.phylo)) gaussian (identity) b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) 1000 100 1 500 0 (0%) 0 27000.11 27321.99 91716340
Estimate l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
b_Intercept 0.086 0.016 0.160 1.003 27000.11 27321.99
b_lg10.male.weight 0.838 0.780 0.896 1.001 43152.52 37327.16

2.3.1 log(males) ~ log(females)

Code
phylogenetic_uncertainty(ln.male.weight ~ ln.female.weight, data = dat,
    sp.id.column = "scientific_name", phylos = trees, family = gaussian(),
    prior = prior, iter = iter, control = list(adapt_delta = 0.99,
        max_treedepth = 15), fit.name = "female_vs_male_size", save.fits = FALSE,
    save.combined = TRUE, path = "./data/processed/", chains = chains,
    cores = cores)
Code
brmsish::extended_summary(read.file = "./data/processed/female_vs_male_size_1000_iterations.rds",
    highlight = TRUE)

2.4 female_vs_male_size_1000_iterations

formula family priors iterations chains thinning warmup diverg_transitions rhats > 1.05 min_bulk_ESS min_tail_ESS seed
1 ln.male.weight ~ ln.female.weight + (1 | gr(scientific_name, cov = vcv.phylo)) gaussian (identity) b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) 1000 100 1 500 0 (0%) 0 28352.56 29483.41 1107860310
Estimate l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
b_Intercept -0.148 -0.347 0.044 1.002 28352.56 29483.41
b_ln.female.weight 1.139 1.060 1.216 1.001 44292.65 37977.85

2.4.1 log10(males) ~ log10(females)

Code
phylogenetic_uncertainty(lg10.male.weight ~ lg10.female.weight, data = dat,
    sp.id.column = "scientific_name", phylos = trees, family = gaussian(),
    prior = prior, iter = iter, control = list(adapt_delta = 0.99,
        max_treedepth = 15), fit.name = "log10_female_vs_male_size",
    save.fits = FALSE, save.combined = TRUE, path = "./data/processed/",
    chains = chains, cores = cores)
Code
brmsish::extended_summary(read.file = "./data/processed/log10_female_vs_male_size_1000_iterations.rds",
    highlight = TRUE)

2.5 log10_female_vs_male_size_1000_iterations

formula family priors iterations chains thinning warmup diverg_transitions rhats > 1.05 min_bulk_ESS min_tail_ESS seed
1 lg10.male.weight ~ lg10.female.weight + (1 | gr(scientific_name, cov = vcv.phylo)) gaussian (identity) b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) 1000 100 1 500 1 (2e-05%) 0 26779.79 29359.06 1451555959
Estimate l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
b_Intercept -0.064 -0.151 0.020 1.002 26779.79 29359.06
b_lg10.female.weight 1.139 1.060 1.217 1.001 41417.59 38690.55

2.6 SSD (Lovich-Gibbons ratio) vs male size

  • SSD represented as aboslute Lovich-Gibbons ratio
  • sex size as log of weight

2.6.1 Absolute SSD vs log male size

Code
phylogenetic_uncertainty(aboluteSSD ~ ln.male.weight, data = dat,
    sp.id.column = "scientific_name", phylos = trees, family = gaussian(),
    prior = prior, iter = iter, control = list(adapt_delta = 0.99,
        max_treedepth = 15), fit.name = "male_vs_abs_SSD", save.fits = FALSE,
    save.combined = TRUE, path = "./data/processed/", chains = chains,
    cores = cores)
Code
brmsish::extended_summary(read.file = "./data/processed/male_vs_abs_SSD_1000_iterations.rds",
    highlight = TRUE)

2.7 male_vs_abs_SSD_1000_iterations

formula family priors iterations chains thinning warmup diverg_transitions rhats > 1.05 min_bulk_ESS min_tail_ESS seed
1 aboluteSSD ~ ln.male.weight + (1 | gr(scientific_name, cov = vcv.phylo)) gaussian (identity) b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) 1000 100 1 500 11 (0.00022%) 0 29241.39 25006.14 664937249
Estimate l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
b_Intercept 0.012 -0.128 0.136 1.002 29241.39 25006.14
b_ln.male.weight 0.065 0.007 0.123 1.002 52993.88 37500.93

2.7.1 Absolute SSD vs log10 male size

Code
phylogenetic_uncertainty(aboluteSSD ~ lg10.male.weight, data = dat,
    sp.id.column = "scientific_name", phylos = trees, family = gaussian(),
    prior = prior, iter = iter, control = list(adapt_delta = 0.99,
        max_treedepth = 15), fit.name = "log10_male_vs_abs_SSD", save.fits = FALSE,
    save.combined = TRUE, path = "./data/processed/", chains = chains,
    cores = cores)
Code
brmsish::extended_summary(read.file = "./data/processed/log10_male_vs_abs_SSD_1000_iterations.rds",
    highlight = TRUE)

2.8 log10_male_vs_abs_SSD_1000_iterations

formula family priors iterations chains thinning warmup diverg_transitions rhats > 1.05 min_bulk_ESS min_tail_ESS seed
1 aboluteSSD ~ lg10.male.weight + (1 | gr(scientific_name, cov = vcv.phylo)) gaussian (identity) b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) 1000 100 1 500 5 (1e-04%) 0 29625.52 28350.92 1057511118
Estimate l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
b_Intercept 0.011 -0.128 0.136 1.002 29625.52 28350.92
b_lg10.male.weight 0.150 0.017 0.285 1.001 50057.46 37967.99

2.8.1 absolute SSD vs log female size

Code
phylogenetic_uncertainty(aboluteSSD ~ ln.female.weight, data = dat,
    sp.id.column = "scientific_name", phylos = trees, family = gaussian(),
    prior = prior, iter = iter, control = list(adapt_delta = 0.99,
        max_treedepth = 15), fit.name = "female_vs_abs_SSD", save.fits = FALSE,
    save.combined = TRUE, path = "./data/processed/", chains = chains,
    cores = cores)
Code
brmsish::extended_summary(read.file = "./data/processed/female_vs_abs_SSD_1000_iterations.rds",
    highlight = TRUE)

2.9 female_vs_abs_SSD_1000_iterations

formula family priors iterations chains thinning warmup diverg_transitions rhats > 1.05 min_bulk_ESS min_tail_ESS seed
1 aboluteSSD ~ ln.female.weight + (1 | gr(scientific_name, cov = vcv.phylo)) gaussian (identity) b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) 1000 100 1 500 4 (8e-05%) 0 35372.25 30277.62 1400504111
Estimate l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
b_Intercept 0.053 -0.093 0.189 1.002 35372.25 30277.62
b_ln.female.weight 0.042 -0.027 0.112 1.002 60413.93 38792.66

2.9.1 absolute SSD vs log10 female size

Code
phylogenetic_uncertainty(aboluteSSD ~ lg10.female.weight, data = dat,
    sp.id.column = "scientific_name", phylos = trees, family = gaussian(),
    prior = prior, iter = iter, control = list(adapt_delta = 0.99,
        max_treedepth = 15), fit.name = "log10_female_vs_abs_SSD",
    save.fits = FALSE, save.combined = TRUE, path = "./data/processed/",
    chains = chains, cores = cores)
Code
brmsish::extended_summary(read.file = "./data/processed/log10_female_vs_abs_SSD_1000_iterations.rds",
    highlight = TRUE)

2.10 log10_female_vs_abs_SSD_1000_iterations

formula family priors iterations chains thinning warmup diverg_transitions rhats > 1.05 min_bulk_ESS min_tail_ESS seed
1 aboluteSSD ~ lg10.female.weight + (1 | gr(scientific_name, cov = vcv.phylo)) gaussian (identity) b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) 1000 100 1 500 2 (4e-05%) 0 33658.82 28921.81 1528172800
Estimate l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
b_Intercept 0.053 -0.095 0.189 1.001 33658.82 28921.81
b_lg10.female.weight 0.096 -0.064 0.259 1.001 57926.09 37884.08

3 Graphs

3.1 Male vs female body mass

Code
fit <- readRDS("./data/processed/log10_male_vs_female_size_1000_iterations.rds")

gg_fit <- conditional_effects(fit)

pred_dat <- gg_fit$lg10.male.weight
pred_dat$Clade <- "Hermits"

fit_summ <- brmsish:::draw_summary(draws = posterior::as_draws_array(fit),
    variables = c("b_Intercept", "b_lg10.male.weight"), robust = TRUE,
    probs = c(0.025, 0.975), spread.type = "MAD")


ggplot(data = dat, mapping = aes(x = lg10.male.weight, y = lg10.female.weight,
    fill = Clade, shape = Clade)) + scale_fill_viridis_d(alpha = 0.5) +
    geom_segment(data = pred_dat, mapping = aes(x = min(pred_dat$lg10.male.weight),
        y = min(pred_dat$estimate__), xend = max(pred_dat$lg10.male.weight),
        yend = max(pred_dat$estimate__))) + geom_ribbon(data = pred_dat,
    aes(ymin = lower__, ymax = upper__), fill = "gray", alpha = 0.3) +
    scale_shape_manual(values = c(21, 22, 23, 21, 22, 23, 21, 22)) +
    geom_point(size = 3, color = "transparent") + theme_classic(base_size = 20) +
    labs(x = "log10(male body mass)", y = "log10(female body mass)")

Code
# ggsave(filename =
# './output/log10_male_vs_absolute_SSD_70dpi.tiff', dpi = 70)
# ggsave(filename =
# './output/log10_male_vs_absolute_SSD_300dpi.tiff', dpi = 300)

3.2 Male body mass vs absolute SSD

Code
fit <- readRDS("./data/processed/log10_male_vs_abs_SSD_1000_iterations.rds")

gg_fit <- conditional_effects(fit)

pred_dat <- gg_fit$lg10.male.weight
pred_dat$Clade <- "Hermits"

fit_summ <- brmsish:::draw_summary(draws = posterior::as_draws_array(fit),
    variables = c("b_Intercept", "b_lg10.male.weight"), robust = TRUE,
    probs = c(0.025, 0.975), spread.type = "MAD")

ggplot(data = dat, mapping = aes(x = lg10.male.weight, y = aboluteSSD,
    fill = Clade, shape = Clade)) + scale_fill_viridis_d(alpha = 0.5) +
    geom_segment(data = pred_dat, mapping = aes(x = min(pred_dat$lg10.male.weight),
        y = min(pred_dat$estimate__), xend = max(pred_dat$lg10.male.weight),
        yend = max(pred_dat$estimate__))) + geom_ribbon(data = pred_dat,
    aes(ymin = lower__, ymax = upper__), fill = "gray", alpha = 0.3) +
    scale_shape_manual(values = c(21, 22, 23, 21, 22, 23, 21, 22)) +
    geom_point(color = viridis(10, alpha = 0.6)[7], size = 3) + theme_classic(base_size = 20) +
    labs(x = "log10(male body mass)", y = "Dimorphism (absolute SSD)")

Code
# ggsave(filename =
# './output/log10_female_vs_absolute_SSD_300dpi.tiff', dpi =
# 300) ggsave(filename =
# './output/log10_female_vs_absolute_SSD_70dpi.tiff', dpi = 70)

3.3 Female body mass vs absolute SSD

Code
fit <- readRDS("./data/processed/log10_female_vs_abs_SSD_1000_iterations.rds")

gg_fit <- conditional_effects(fit)

pred_dat <- gg_fit$lg10.female.weight
pred_dat$Clade <- "Hermits"

fit_summ <- brmsish:::draw_summary(draws = posterior::as_draws_array(fit),
    variables = c("b_Intercept", "b_lg10.female.weight"), robust = TRUE,
    probs = c(0.025, 0.975), spread.type = "MAD")

ggplot(data = dat, mapping = aes(x = lg10.female.weight, y = aboluteSSD,
    fill = Clade, shape = Clade)) + scale_fill_viridis_d(alpha = 0.5) +
    # geom_segment(data = pred_dat, mapping = aes(x =
    # min(pred_dat$lg10.female.weight), y =
    # min(pred_dat$estimate__), xend =
    # max(pred_dat$lg10.female.weight), yend =
    # max(pred_dat$estimate__))) + geom_ribbon(data = pred_dat,
    # aes(ymin = lower__, ymax = upper__), fill = 'gray', alpha
    # = 0.3) +
scale_shape_manual(values = c(21, 22, 23, 21, 22, 23, 21, 22)) + geom_point(color = viridis(10,
    alpha = 0.6)[7], size = 3) + theme_classic(base_size = 20) + labs(x = "log10(female body mass)",
    y = "Dimorphism (absolute SSD)")

Code
# ggsave(filename =
# './output/male_vs_female_size_10log_300dpi.tiff', dpi = 300)
# ggsave(filename =
# './output/male_vs_female_size_10log_70dpi.tiff', dpi = 70)
Code
fill_color <- viridis(10)[7]

dat$Clade <- factor(dat$Clade, levels = c("Bees", "Coquettes", "Hermits", "Brilliants", "Emeralds", "Mangoes", "Mountain Gems", "Topazes"))

agg_dat <- aggregate(`scientific_name` ~ Clade, data = dat, length)
agg_dat$`Lovich-Gibbons.ratio` <- NA
agg_dat$n.labels <- paste("n =", agg_dat$`scientific_name`)

# set.seed(12)
trans <-  function(height = 0, ...) ggplot2::position_jitter(height = height, ...)

# composed box plot
ggplot(dat, aes(y = `Lovich-Gibbons.ratio`, x = Clade)) +
    geom_hline(yintercept = 0, lty = 2) +     
## add half-violin from {ggdist} package
  ggdist::stat_halfeye(
    fill = fill_color,
    alpha = 0.5,
    ## custom bandwidth
    adjust = .5,
    ## adjust height
    width = .6,
    .width = 0,
    ## move geom to the cright
    justification = -.2,
    point_colour = NA
  ) +
  geom_boxplot(fill = fill_color,
    width = .15,
    ## remove outliers
    outlier.shape = NA ## `outlier.shape = NA` works as well
  ) +
  ## add justified jitter from the {gghalves} package
  # geom_half_point(
  #   color = fill_color,
  #   ## draw jitter on the left
  #   side = "l",
  #   ## control range of jitter
  #   range_scale = .4,
  #   ## add some transparency
  #   alpha = .5,
  #   transformation = ggplot2::position_jitter(height = 0)
  # 
  # ) +
    labs(x="Clade", y= "Lovich-Gibbons ratio"
  ) +
  ylim(c(-0.39, 0.145)) +
  geom_text(data = agg_dat, aes(y = rep(-0.387, nrow(agg_dat)), x = Clade, label = n.labels), nudge_x = 0, size = 6) +
     theme_classic(base_size = 18) +
theme(axis.text.x = element_text(angle = 30, hjust = 1)) 

4 Combined model diagnostics

Code
check_rds_fits(path = "./data/processed", html = TRUE)
fit formula family priors iterations chains thinning warmup diverg_transitions rhats > 1.05 min_bulk_ESS min_tail_ESS seed
1 female_vs_abs_SSD_1000_iterations.rds aboluteSSD ~ ln.female.weight + (1 | gr(scientific_name, cov = vcv.phylo)) gaussian (identity) b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) 1000 100 1 500 4 (8e-05%) 0 12530 19871 1400504111
2 female_vs_abs_SSD.rds aboluteSSD ~ ln.female.weight + (1 | gr(scientific_name, cov = vcv.phylo)) gaussian (identity) b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) 10000 100 1 5000 99 (0.000198%) 0 116310 187297 637705020
3 female_vs_male_size_1000_iterations.rds ln.male.weight ~ ln.female.weight + (1 | gr(scientific_name, cov = vcv.phylo)) gaussian (identity) b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) 1000 100 1 500 0 (0%) 0 7079 10497 1107860310
4 female_vs_male_size.rds ln.male.weight ~ ln.female.weight + (1 | gr(scientific_name, cov = vcv.phylo)) gaussian (identity) b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) 10000 100 1 5000 6 (1.2e-05%) 0 74162 120659 827109765
5 log10_female_vs_abs_SSD_1000_iterations.rds aboluteSSD ~ lg10.female.weight + (1 | gr(scientific_name, cov = vcv.phylo)) gaussian (identity) b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) 1000 100 1 500 2 (4e-05%) 0 11334 17553 1528172800
6 log10_female_vs_abs_SSD.rds aboluteSSD ~ lg10.female.weight + (1 | gr(scientific_name, cov = vcv.phylo)) gaussian (identity) b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) 10000 100 1 5000 150 (3e-04%) 0 114499 175073 1831524102
7 log10_female_vs_male_size_1000_iterations.rds lg10.male.weight ~ lg10.female.weight + (1 | gr(scientific_name, cov = vcv.phylo)) gaussian (identity) b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) 1000 100 1 500 1 (2e-05%) 0 6814 9015 1451555959
8 log10_female_vs_male_size.rds lg10.male.weight ~ lg10.female.weight + (1 | gr(scientific_name, cov = vcv.phylo)) gaussian (identity) b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) 10000 100 1 5000 0 (0%) 0 73089 115758 1505167971
9 log10_male_vs_abs_SSD_1000_iterations.rds aboluteSSD ~ lg10.male.weight + (1 | gr(scientific_name, cov = vcv.phylo)) gaussian (identity) b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) 1000 100 1 500 5 (1e-04%) 0 10660 17029 1057511118
10 log10_male_vs_abs_SSD.rds aboluteSSD ~ lg10.male.weight + (1 | gr(scientific_name, cov = vcv.phylo)) gaussian (identity) b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) 10000 100 1 5000 76 (0.000152%) 0 109133 170826 1860874560
11 log10_male_vs_female_size_1000_iterations.rds lg10.female.weight ~ lg10.male.weight + (1 | gr(scientific_name, cov = vcv.phylo)) gaussian (identity) b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) 1000 100 1 500 0 (0%) 0 7012 8034 91716340
12 log10_male_vs_female_size.rds lg10.female.weight ~ lg10.male.weight + (1 | gr(scientific_name, cov = vcv.phylo)) gaussian (identity) b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) 10000 100 1 5000 2 (4e-06%) 0 72456 112184 722558904
13 male_vs_abs_SSD_1000_iterations.rds aboluteSSD ~ ln.male.weight + (1 | gr(scientific_name, cov = vcv.phylo)) gaussian (identity) b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) 1000 100 1 500 11 (0.00022%) 0 11299 18115 664937249
14 male_vs_abs_SSD.rds aboluteSSD ~ ln.male.weight + (1 | gr(scientific_name, cov = vcv.phylo)) gaussian (identity) b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) 10000 100 1 5000 90 (0.00018%) 0 108042 172985 662186260
15 male_vs_female_size_1000_iterations.rds ln.female.weight ~ ln.male.weight + (1 | gr(scientific_name, cov = vcv.phylo)) gaussian (identity) b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) 1000 100 1 500 1 (2e-05%) 0 7649 10987 1984988351
16 male_vs_female_size.rds ln.female.weight ~ ln.male.weight + (1 | gr(scientific_name, cov = vcv.phylo)) gaussian (identity) b-normal(0, 10) Intercept-normal(0, 50) sd-student_t(3, 0, 20) sigma-student_t(3, 0, 20) 10000 100 1 5000 6 (1.2e-05%) 0 70547 104714 1535398272

Takeaways

  • Dimorpism increases with body size in males but not in females

 


 

Session information

R version 4.5.0 (2025-04-11)
Platform: x86_64-pc-linux-gnu
Running under: Ubuntu 22.04.5 LTS

Matrix products: default
BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.10.0 
LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.10.0  LAPACK version 3.10.0

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=es_CR.UTF-8        LC_COLLATE=en_US.UTF-8    
 [5] LC_MONETARY=es_CR.UTF-8    LC_MESSAGES=en_US.UTF-8   
 [7] LC_PAPER=es_CR.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=es_CR.UTF-8 LC_IDENTIFICATION=C       

time zone: America/Costa_Rica
tzcode source: system (glibc)

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] gghalves_0.1.4      phangorn_2.12.1     ggplot2_4.0.0      
 [4] viridis_0.6.5       viridisLite_0.4.2   sketchy_1.0.5      
 [7] brmsish_1.0.0       brms_2.23.0         Rcpp_1.1.0         
[10] ggtree_3.16.3       readxl_1.4.5        ape_5.8-1          
[13] xaringanExtra_0.8.0 rprojroot_2.1.1     formatR_1.14       
[16] knitr_1.50          kableExtra_1.4.0   

loaded via a namespace (and not attached):
  [1] pbapply_1.7-4         gridExtra_2.3         inline_0.3.21        
  [4] remotes_2.5.0         sandwich_3.1-1        rlang_1.1.6          
  [7] magrittr_2.0.4        multcomp_1.4-28       matrixStats_1.5.0    
 [10] compiler_4.5.0        loo_2.8.0             reshape2_1.4.4       
 [13] systemfonts_1.3.1     vctrs_0.6.5           quadprog_1.5-8       
 [16] stringr_1.6.0         pkgconfig_2.0.3       arrayhelpers_1.1-0   
 [19] crayon_1.5.3          fastmap_1.2.0         backports_1.5.0      
 [22] labeling_0.4.3        fontawesome_0.5.3     rmarkdown_2.30       
 [25] purrr_1.2.0           xfun_0.54             aplot_0.2.8          
 [28] jsonlite_2.0.0        tidybayes_3.0.7       uuid_1.2-1           
 [31] parallel_4.5.0        R6_2.6.1              StanHeaders_2.32.10  
 [34] stringi_1.8.7         RColorBrewer_1.1-3    cellranger_1.1.0     
 [37] estimability_1.5.1    rstan_2.32.7          zoo_1.8-14           
 [40] bayesplot_1.14.0      Matrix_1.7-3          splines_4.5.0        
 [43] igraph_2.2.1          tidyselect_1.2.1      rstudioapi_0.17.1    
 [46] abind_1.4-8           yaml_2.3.10           codetools_0.2-20     
 [49] curl_7.0.0            pkgbuild_1.4.8        plyr_1.8.9           
 [52] lattice_0.22-7        tibble_3.3.0          Biobase_2.68.0       
 [55] treeio_1.32.0         withr_3.0.2           bridgesampling_1.1-2 
 [58] S7_0.2.0              posterior_1.6.1       coda_0.19-4.1        
 [61] evaluate_1.0.5        gridGraphics_0.5-1    survival_3.8-3       
 [64] RcppParallel_5.1.11-1 ggdist_3.3.3          xml2_1.4.1           
 [67] pillar_1.11.1         tensorA_0.36.2.1      packrat_0.7.0        
 [70] stats4_4.5.0          checkmate_2.3.3       ggfun_0.2.0          
 [73] distributional_0.5.0  generics_0.1.4        rstantools_2.5.0     
 [76] scales_1.4.0          tidytree_0.4.6        xtable_1.8-4         
 [79] glue_1.8.0            emmeans_1.11.1        lazyeval_0.2.2       
 [82] tools_4.5.0           fs_1.6.6              mvtnorm_1.3-3        
 [85] fastmatch_1.1-6       cowplot_1.2.0         grid_4.5.0           
 [88] tidyr_1.3.1           QuickJSR_1.8.1        nlme_3.1-168         
 [91] patchwork_1.3.0       cli_3.6.5             textshaping_1.0.4    
 [94] svUnit_1.0.8          svglite_2.2.2         Brobdingnag_1.2-9    
 [97] dplyr_1.1.4           V8_6.0.4              gtable_0.3.6         
[100] yulab.utils_0.2.0     digest_0.6.37         BiocGenerics_0.54.0  
[103] ggplotify_0.1.2       TH.data_1.1-3         htmlwidgets_1.6.4    
[106] farver_2.1.2          htmltools_0.5.8.1     lifecycle_1.0.4      
[109] MASS_7.3-65