Skip to contents

Overview

The fit_bayesian_birth() function estimates birth size (\(b_{50}\)) by comparing length distributions of embryos and free-swimming individuals using Bayesian probit regression.

Key output: The length at which 50% of individuals have transitioned from embryo to free-swimming status.

The Model

The probability of being free-swimming follows a probit model:

\[P(\text{free-swimming}_i) = \Phi[\beta \cdot (L_i - b_{50})]\]

where:

  • \(\Phi(\cdot)\) is the standard normal CDF
  • \(b_{50}\) is the length at 50% transition probability
  • \(\beta > 0\) controls the sharpness of the transition

Why probit? The probit link assumes that underlying developmental readiness is normally distributed across individuals—a biologically intuitive interpretation. For a detailed derivation, see the Probit Link section in the Statistical Methods guide.

Basic Usage

library(vitalBayes)
library(data.table)

# Load example data (simulated von Bertalanffy growth data)
data(growth_data)

# Separate embryo and free-swimming lengths
embryo_lengths <- growth_data[embryo == TRUE, fl]
freeswim_lengths <- growth_data[embryo == FALSE, fl]

# Fit the birth model
birth_fit <- fit_bayesian_birth(
 embryo_lts        = embryo_lengths,
 free_swimming_lts = freeswim_lengths,
 chains            = 4,
 parallel          = TRUE
)

Examining Results

# Core parameter estimates
birth_fit$summary(c("b50", "slope", "transition_width"))

# Posterior predictive checks
birth_fit$summary(c("mean_p_embryo", "mean_p_freeswim", "prop_correct_rep"))

Customizing Priors

The function automatically derives prior centers from the data, but you can override:

birth_fit <- fit_bayesian_birth(
 embryo_lts        = embryo_lengths,
 free_swimming_lts = freeswim_lengths,
 mean_b50          = 35,      # Prior mean for b50 (cm)
 sd_b50            = 5,       # Prior SD
 mean_slope        = 0,       # Prior mean for log(slope)
 sd_slope          = 1,       # Prior SD for log(slope)
 adapt_delta       = 0.95     # Increase if divergences occur
)

Visualization

# Quick visualization
plot_birth_ogive(birth_fit, embryo_lengths, freeswim_lengths)

# Extract b50 for reporting
b50_summary <- birth_fit$summary("b50")
cat(sprintf("b50 = %.1f cm (95%% CI: %.1f – %.1f)\n",
           b50_summary$median, b50_summary$q5, b50_summary$q95))

Using Output in Downstream Models

The \(b_{50}\) estimate serves as the prior for birth length (\(L_0\)) in growth models:

# The birth fit can be passed directly to growth models
growth_fit <- fit_bayesian_growth(
 lt        = "fl",
 age       = "age", 
 sex       = "sex",
 data      = growth_data[embryo == FALSE],
 birth_fit = birth_fit  # Automatically extracts L0 prior
)

Working with Limited Data

For datasets with few embryos, consider using the limited_data example dataset to explore prior sensitivity:

# Load the small sample dataset (24F, 18M, 5 embryos)
data(limited_data)

# With sparse embryo data, priors become more influential
birth_fit_limited <- fit_bayesian_birth(
 embryo_lts        = limited_data[embryo == TRUE, fl],
 free_swimming_lts = limited_data[embryo == FALSE, fl],
 cv_b50            = 0.2  # Tighter prior when data are sparse
)

Troubleshooting

Issue Solution
Divergent transitions Increase adapt_delta (0.95 → 0.99)
Wide credible intervals Check for data overlap; consider more informative priors
Poor classification Verify embryo/free-swimming labels in data

See Also


This document is part of the vitalBayes R package. For bug reports, feature requests, or questions, please visit the GitHub repository.