This project quantifies the "selection shadow" - the decline in the force of natural selection with age - across countries over 70 years of demographic history (1950+). By calculating Hamilton's force of selection s(x) using global demographic data, we reconstruct the selection landscape of the human species to understand how the demographic transition has reshaped evolutionary pressures.
The demographic transition creates an evolutionary paradox: falling mortality may extend the selection shadow (pushing selection to later ages), while declining fertility may dilute selection intensity. We investigate whether the net result is an expansion or contraction of the window for late-onset mutation accumulation.
GitHub: https://github.com/donertas-group/human_selection_shadow
Explore how demographic parameters shape the selection shadow:
Launch Selection Shadow Explorer →
Adjust mortality, fertility, and population growth in real-time to see how they affect evolutionary selection pressure across the lifespan.
- R (>= 4.5.2)
- RStudio (recommended)
- Clone the repository
- Open
selection_shadow.Rprojin RStudio - Restore the R environment:
renv::restore()
Scripts are numbered and should be run sequentially:
Rscript scripts/00-setup.R # Load libraries, define functions
Rscript scripts/01-simulations.R # Generate simulated demographic scenarios
Rscript scripts/02-dataPrep.R # Process raw OWID demographic data
Rscript scripts/03-EDAViz.R # Exploratory visualizations (Figures S1-S5)
Rscript scripts/04-selection_shadow.R # Calculate s(x) for all country-years
Rscript scripts/05-selection_metrics.R # Summary metrics from s(x) curves
Rscript scripts/06-temporal.R # Temporal shifts analysis (1950s vs 2010s)
Rscript scripts/07-determinants.R # Demographic drivers of selection metrics
Rscript scripts/08-ageing_mechanisms.R # Implications for MA/AP ageing theoriesshiny::runApp("scripts/shiny/app.R")├── scripts/
│ ├── 00-setup.R # Core functions and visualization settings
│ ├── 01-simulations.R # Synthetic scenario simulations
│ ├── 02-dataPrep.R # Data processing pipeline
│ ├── 03-EDAViz.R # Exploratory data analysis
│ ├── 04-selection_shadow.R # Main s(x) calculations
│ ├── 05-selection_metrics.R # Summary statistics
│ ├── 06-temporal.R # Temporal shifts by demographic stage
│ ├── 07-determinants.R # Regression analysis of drivers
│ ├── 08-ageing_mechanisms.R # Ageing theory implications
│ ├── shiny/app.R # Interactive Shiny application
├── data/
│ ├── raw/ # OWID demographic CSV files
│ └── processed/ # Generated RDS files
├── results/
│ ├── figures/ # Output plots (PDF, PNG, RDS)
│ └── tables/ # Output tables (CSV, TSV, RDS)
└── renv/ # Package management
Hamilton quantified selection intensity at each age:
| Component | Meaning |
|---|---|
s(x) |
Selection intensity at age x |
x |
Age at which selection is measured |
y |
Summation index (ages from x to ω) |
ω |
Maximum lifespan |
r |
Population growth rate |
L(y) |
Person-years lived: [(l(y) + l(y+n))/2] × n |
m(y) |
Maternity: fertility rate at age y |
e^(-ry) |
Discounting: weights early reproduction higher |
T |
Generation time: mean age of reproduction |
All data is downloaded from Our World in Data. CSV files are stored in data/raw/:
- Population by age group and sex
- Birth rates by age of mother
- Death rates by age group
- Population growth rates
Intermediate and final datasets can be created by running the scripts in scripts/ in the correct order. The processed data will be stored in data/processed/.