| Title: | Tidy Access to Spanish INE Demographic Data |
| Version: | 0.1.0 |
| Description: | Provides tidy, harmonized access to demographic data from the Spanish National Statistics Institute (INE) fenomenos demograficos domain, including population, births, and deaths, retrieved live via the official 'ineapir' API wrapper, with optional spatial integration at municipality and province level via 'mapSpain'. Mortality indicators follow the Human Mortality Database Methods Protocol, including the average age at death in infancy method of Andreev and Kingkade (2015) <doi:10.4054/DemRes.2015.33.13>. |
| License: | MIT + file LICENSE |
| Encoding: | UTF-8 |
| RoxygenNote: | 7.3.3 |
| Imports: | dplyr, ggplot2, httr2, ineapir, mapSpain, purrr, readr, rlang, scales, sf, stringi, stringr, tibble, tidyr |
| Suggests: | mockery, R.rsp, testthat (≥ 3.0.0), withr |
| Config/testthat/edition: | 3 |
| Depends: | R (≥ 4.1.0) |
| LazyData: | true |
| Collate: | 'helpers.R' 'death_rates.R' 'life_tables.R' 'abridged_life_tables.R' 'births.R' 'data.R' 'deaths.R' 'decomposition.R' 'download_ine_data.R' 'exposure.R' 'get_ine_demog.R' 'get_ine_geo.R' 'hmd_write.R' 'indicators.R' 'inedemogR-package.R' 'lexis.R' 'list_ine_indicators.R' 'plot_demog.R' 'plot_ine_map.R' 'population.R' 'update_ine_data.R' |
| VignetteBuilder: | R.rsp |
| NeedsCompilation: | no |
| Packaged: | 2026-08-20 06:34:41 UTC; josecaro |
| Author: | J. R. Caro-Barrera [aut, cre, cph] |
| Maintainer: | J. R. Caro-Barrera <jrcaro@uco.es> |
| Repository: | CRAN |
| Date/Publication: | 2026-08-23 10:30:08 UTC |
inedemogR: Tidy Access to Spanish INE Demographic Data
Description
Provides tidy, harmonized access to demographic data from the Spanish National Statistics Institute (INE) fenomenos demograficos domain, including population, births, and deaths, retrieved live via the official 'ineapir' API wrapper, with optional spatial integration at municipality and province level via 'mapSpain'. Mortality indicators follow the Human Mortality Database Methods Protocol, including the average age at death in infancy method of Andreev and Kingkade (2015) doi:10.4054/DemRes.2015.33.13.
Author(s)
Maintainer: J. R. Caro-Barrera jrcaro@uco.es [copyright holder]
Age dependency ratios
Description
Computes youth, old-age, and total age dependency ratios per province and
year from age-disaggregated population data. Requires an age breakdown,
so it operates on get_ine_population()'s output, not
get_ine_demog()'s population_total indicator (which has no age
column and cannot be used here).
Usage
age_dependency_ratio(pop_df, young_max = 14L, old_min = 65L)
Arguments
pop_df |
Population tibble as returned by |
young_max |
Integer, the maximum age counted as "young" (default
|
old_min |
Integer, the minimum age counted as "old" (default |
Value
A tibble with nuts3_code, province_name, year,
youth_dependency_ratio, old_age_dependency_ratio,
total_dependency_ratio (all per 100 working-age population).
Examples
pop <- tibble::tibble(
nuts3_code = "ES111", province_name = "A Coruna", year = 2023,
age = c(0, 20, 70), total = c(100, 300, 150)
)
age_dependency_ratio(pop)
Age-specific fertility rates (ASFR)
Description
Computes age-specific fertility rates (births per 1,000 women of that
age) per province, year, and single year of age, joining
get_ine_births_by_age() and get_ine_population() output. This is
the schedule underlying total_fertility_rate(),
mean_age_at_childbearing(), gross_reproduction_rate(), and
net_reproduction_rate() - unlike general_fertility_rate(), which
collapses reproductive age into one aggregate rate,
age_specific_fertility_rate() keeps the full age schedule, the input
a true total fertility rate requires.
Usage
age_specific_fertility_rate(
births_age_df,
pop_df,
age_min = 15L,
age_max = 49L
)
Arguments
births_age_df |
Tibble as returned by |
pop_df |
Population tibble as returned by |
age_min |
Integer, the youngest single-year age included
(default |
age_max |
Integer, the oldest single-year age included
(default |
Value
A tibble with nuts3_code, province_name, year, age,
asfr (all births per 1,000 women of that age), asfr_female
(births of female newborns per 1,000 women of that age - the input
gross_reproduction_rate() and net_reproduction_rate() need).
Examples
births_age <- tibble::tibble(
nuts3_code = "ES111", province_name = "A Coruna", year = 2023,
age = c(20, 30), female = c(10, 25), total = c(20, 50)
)
pop <- tibble::tibble(
nuts3_code = "ES111", year = 2023, age = c(20, 30), female = c(2000, 2500)
)
age_specific_fertility_rate(births_age, pop)
Aging index
Description
Computes the aging index (elderly per 100 children) per province and
year from age-disaggregated population data. Requires an age breakdown,
so it operates on get_ine_population()'s output, not
get_ine_demog()'s population_total indicator.
Usage
aging_index(pop_df, young_max = 14L, old_min = 65L)
Arguments
pop_df |
Population tibble as returned by |
young_max |
Integer, the maximum age counted as "young" (default
|
old_min |
Integer, the minimum age counted as "old" (default |
Value
A tibble with nuts3_code, province_name, year,
aging_index.
Examples
pop <- tibble::tibble(
nuts3_code = "ES111", province_name = "A Coruna", year = 2023,
age = c(0, 20, 70), total = c(100, 300, 150)
)
aging_index(pop)
Andreev-Kingkade a0 (mean age at death in the first year of life)
Description
Implements the Andreev-Kingkade (2015) piecewise regression specified in HMD Methods Protocol V6 (replacing the older Coale-Demeny approximation).
Usage
andreev_kingkade_a0(m0, sex = c("female", "male"))
Arguments
m0 |
Central death rate at age 0. |
sex |
|
Value
Numeric a0 value.
Examples
andreev_kingkade_a0(0.004, "female")
andreev_kingkade_a0(0.15, "male")
Birth-to-death ratio
Description
Computes the birth-to-death ratio (live births per death) per
geography and year. Unlike age_dependency_ratio()/aging_index()/
sex_ratio(), this needs no age breakdown, so it operates directly on
get_ine_demog()'s totals (System A) rather than get_ine_population()
(System B) — fetch both births_total and deaths_total in one call
and pass the result straight through.
Usage
birth_death_ratio(df)
Arguments
df |
Output of |
Value
A tibble with GEOID, NAME, year, birth_death_ratio. A
value of 2 means 2 live births per death; 0.5 means 1 birth per
2 deaths.
Examples
df <- tibble::tibble(
GEOID = c("15", "28"), NAME = c("A Coruna", "Madrid"), year = 2023,
births_total = c(3000, 30000), deaths_total = c(6000, 25000)
)
birth_death_ratio(df)
Build an abridged (5-year age group) period life table
Description
Constructs a full abridged period life table (age groups "00-04",
"05-09", ..., "95-99", "100+") directly from grouped central
death rates, per the standard discrete abridged life-table method
(Chiang's nqx formula; Preston, Heuveline & Guillot 2001, Ch. 3).
Complements build_life_table()'s single-year (1x1) tables - use
this when comparing against other agencies' published abridged
tables, or when only grouped-age data is available. The youngest
group ("00-04") is the one exception to using mx_5x1 alone: it is
built from an exact single-year sub-table using mx_1x1's
Andreev-Kingkade a0 (see andreev_kingkade_a0()), avoiding the
external nax(0-4) regression a from-mx_5x1-alone method would
otherwise need for that interval's sharp infant-mortality gradient.
Usage
build_abridged_life_table(mx_1x1, mx_5x1, sex = c("female", "male"))
Arguments
mx_1x1 |
tibble with columns |
mx_5x1 |
tibble with columns |
sex |
|
Value
tibble: age_group, age_start, n (interval width, NA
for the open interval), mx, ax, qx, lx, dx, Lx, Tx, ex.
Examples
mx1 <- data.frame(age = 0:4, mx = c(0.004, 0.0003, 0.0002, 0.0002, 0.0002))
mx5 <- data.frame(
age_group = c("00-04", "05-09", "100+"), mx = c(0.0006, 0.0001, 0.35)
)
build_abridged_life_table(mx1, mx5, "female")
Build abridged period life tables for every province
Description
Constructs female, male, and both-sex abridged (5-year age group)
period life tables for every province and year present in mx_5x1,
from compute_death_rates()'s mx_1x1/mx_5x1 output. See
build_abridged_life_table() for the method; build_life_tables()
for the single-year (1x1) equivalent this complements.
Usage
build_abridged_life_tables(mx_1x1, mx_5x1)
Arguments
mx_1x1 |
Output of the |
mx_5x1 |
Output of the |
Value
list(fltper, mltper, bltper, qc): each a tibble with
nuts3_code, province_name, year, age_group, age_start,
n, mx, ax, qx, lx, dx, Lx, Tx, ex; qc is a named
list of validate_abridged_life_table() results.
Examples
mx_1x1 <- tibble::tibble(
nuts3_code = "ES111", province_name = "A Coruna", year = 2023,
age = 0:4, mx_female = c(0.004, 0.0003, 0.0002, 0.0002, 0.0002),
mx_male = c(0.005, 0.0004, 0.0003, 0.0003, 0.0003),
mx_total = c(0.0045, 0.00035, 0.00025, 0.00025, 0.00025)
)
mx_5x1 <- tibble::tibble(
nuts3_code = "ES111", province_name = "A Coruna", year = 2023,
age_group = c("00-04", "100+"),
mx_female = c(0.0006, 0.35), mx_male = c(0.0008, 0.4), mx_total = c(0.0007, 0.38)
)
alt <- build_abridged_life_tables(mx_1x1, mx_5x1)
alt$fltper
Build a period life table from a mortality schedule
Description
Constructs a full 1x1 period life table from a smoothed mx series
spanning ages 0:110, per HMD Methods Protocol V6: Andreev-Kingkade a0
at age 0, a(1) = 0.4, a(x) = 0.5 elsewhere; the open age interval closes
with qx = 1 and Lx = lx/mx.
Usage
build_life_table(mx_df, sex = c("female", "male"))
Arguments
mx_df |
tibble with columns |
sex |
|
Value
tibble: age, mx, qx, ax, lx, dx, Lx, Tx, ex.
Examples
mx <- data.frame(age = 0:5, mx = c(0.004, 0.0003, 0.0002, 0.0002, 0.0002, 0.0002))
build_life_table(mx, "female")
Build period life tables for every province
Description
Constructs female, male, and both-sex 1x1 period life tables for every
province and year present in mx_1x1, per SHMD Protocol Section 12,
Step 6: Kannisto smoothing/extrapolation of old-age mortality (fitted on
ages 80-95, extended to 110+), then standard life-table recursion with
the Andreev-Kingkade a0.
Usage
build_life_tables(mx_1x1)
Arguments
mx_1x1 |
Output of the |
Value
list(fltper, mltper, bltper, qc): each a tibble with
nuts3_code, province_name, year, age, mx, qx, ax, lx,
dx, Lx, Tx, ex; qc is a named list of
validate_life_table() results, one per province/year/sex table
that failed validation.
Examples
mx_1x1 <- tibble::tibble(
nuts3_code = "ES111", province_name = "A Coruna", year = 2023,
age = 0:5,
mx_female = c(0.004, 0.0003, 0.0002, 0.0002, 0.0002, 0.0002),
mx_male = c(0.005, 0.0004, 0.0003, 0.0003, 0.0003, 0.0003),
mx_total = c(0.0045, 0.00035, 0.00025, 0.00025, 0.00025, 0.00025)
)
lt <- build_life_tables(mx_1x1)
lt$fltper
Compute central death rates for every province
Description
Computes 1x1 (single-year age/period), 5x1 (5-year age group), and
age-standardised (ESP 2013) death rates for every province present in
both deaths and exposure, per SHMD Protocol Section 12, Step 5.
Usage
compute_death_rates(deaths, exposure)
Arguments
deaths |
Output of the |
exposure |
Output of the |
Value
list(mx_1x1, mx_5x1, asdr, qc), each a tibble with nuts3_code,
province_name plus the rate columns; qc is the output of
validate_death_rates() run on mx_1x1.
Examples
deaths <- tibble::tibble(
nuts3_code = "ES111", province_name = "A Coruna", year = 2023,
age = c(0, 1), female = c(1, 0), male = c(1, 1), total = c(2, 1)
)
exposure <- tibble::tibble(
nuts3_code = "ES111", province_name = "A Coruna", year = 2023,
age = c(0, 1), female = c(500, 490), male = c(510, 505), total = c(1010, 995)
)
rates <- compute_death_rates(deaths, exposure)
rates$mx_1x1
rates$asdr
Compute exposure-to-risk for every province
Description
Computes E(x,t) = 1/2[P(x,t) + P(x,t+1)] + 1/2[D_upper(x,t) -
D_lower(x,t)] for every province present in both population and
deaths, per SHMD Protocol Section 12, Step 4. INE's Tempus3 death
tables don't carry a birth-cohort split, so the Lexis triangle is
derived via the documented 50/50 fallback (HMD Methods Protocol V6
Appendix A) unless deaths already carries a cohort column.
Usage
compute_exposure(population, deaths)
Arguments
population |
Output of the |
deaths |
Output of the |
Details
Death registration lags population estimates by about a year, so
population commonly includes a most-recent year (e.g. a Jan-1 stock
snapshot) with no corresponding rows anywhere in deaths yet. That
year is still used as the P(x,t+1) boundary for computing the
previous year's exposure, but is not included in the returned
exposure rows itself — treating an entirely-absent year as zero deaths
(rather than missing data) would mechanically produce zero mortality
for that year, and downstream a nonsensical inflated life expectancy.
Value
list(data, qc): data is a tibble with columns nuts3_code,
province_name, year, age, female, male, total (exposure),
is_boundary_year, is_missing_source_pop; qc is the output of
validate_exposure().
Examples
population <- tibble::tibble(
nuts3_code = "ES111", province_name = "A Coruna",
year = c(2022, 2023), age = 0,
female = c(100, 105), male = c(105, 110), total = c(205, 215)
)
deaths <- tibble::tibble(
nuts3_code = "ES111", province_name = "A Coruna",
year = c(2022, 2023), age = 0,
female = c(1, 1), male = c(1, 2), total = c(2, 3)
)
compute_exposure(population, deaths)
Crude birth rate
Description
Computes the crude birth rate (births per 1,000 population) per province
and year, joining get_ine_births() and get_ine_population() output.
Usage
crude_birth_rate(births_df, pop_df)
Arguments
births_df |
Births tibble as returned by |
pop_df |
Population tibble as returned by |
Details
This is a crude birth rate (total births / total population), not
a total fertility rate (TFR). get_ine_births() itself has no
age-of-mother breakdown, so crude_birth_rate() cannot compute a TFR
on its own — for a true TFR, use get_ine_births_by_age() with
age_specific_fertility_rate()/total_fertility_rate() instead. Do not
substitute crude_birth_rate() for TFR in fertility analysis.
Value
A tibble with nuts3_code, province_name, year, cbr.
Examples
births <- tibble::tibble(
nuts3_code = "ES111", province_name = "A Coruna", year = 2023, total = 100
)
pop <- tibble::tibble(
nuts3_code = "ES111", year = 2023, age = c(0, 1), total = c(5000, 5000)
)
crude_birth_rate(births, pop)
Crude death rate
Description
Computes the crude death rate (deaths per 1,000 population) per
province and year, joining get_ine_deaths() and get_ine_population()
output. The symmetric counterpart to crude_birth_rate() — see
rate_of_natural_increase() to combine the two.
Usage
crude_death_rate(deaths_df, pop_df)
Arguments
deaths_df |
Deaths tibble as returned by |
pop_df |
Population tibble as returned by |
Value
A tibble with nuts3_code, province_name, year, cdr.
Examples
deaths <- tibble::tibble(
nuts3_code = "ES111", province_name = "A Coruna", year = 2023,
age = c(0, 1), total = c(1, 49)
)
pop <- tibble::tibble(
nuts3_code = "ES111", year = 2023, age = c(0, 1), total = c(5000, 5000)
)
crude_death_rate(deaths, pop)
Decompose a difference in life expectancy at birth by age
Description
Attributes the difference in life expectancy at birth (e0) between
two life tables to age-specific contributions, using either Arriaga's
(1984) or Pollard's (1988) method. Arriaga's is an exact discrete
decomposition: sum(contribution) recovers e2(0) - e1(0) exactly.
Pollard's is exact only in the continuous limit; applied to a
single-year life table, sum(contribution) is a close but not exact
approximation of e2(0) - e1(0) - the approximation error grows with
how steeply mortality changes with age (a few percent of the total
gap under a fast-rising hazard is possible), so treat Arriaga's
(the default) as the primary result and Pollard's as a cross-check,
per Ponnapalli (2005)'s finding that the two methods' age patterns
agree closely without being identical. Use this to answer "how much
of the life-expectancy gap
between province A and B (or between year Y1 and Y2) comes from
mortality at each age?" - complementing life_expectancy_summary()/
life_expectancy(), which report e0/e65 but don't explain why
two values differ.
Usage
decompose_life_expectancy(lt1, lt2, method = c("arriaga", "pollard"))
Arguments
lt1 |
A single life table (the "before"/reference table) - one
province-year-sex slice of |
lt2 |
The "after"/comparison life table, same shape as |
method |
|
Value
A tibble with age, contribution (years of the e2(0) - e1(0) gap attributable to mortality differences at that age;
positive means that age group contributed to a gain from lt1 to
lt2).
Examples
age <- 0:100
lt1 <- build_life_table(
data.frame(age = age, mx = 0.0004 * exp(0.075 * age)), "female"
)
lt2 <- build_life_table(
data.frame(age = age, mx = 0.0003 * exp(0.070 * age)), "female"
)
decomp <- decompose_life_expectancy(lt1, lt2)
sum(decomp$contribution)
lt2$ex[1] - lt1$ex[1]
Download SHMD pipeline data to a local folder
Description
Runs the requested stage(s) of the SHMD (Spanish subnational Human
Mortality Database) protocol pipeline — retrieval of province-level
births/deaths/population from INE, exposure-to-risk, central death
rates, and period life tables — and writes the results into out_dir
as .csv and/or HMD-format .txt files, so they can be inspected,
shared, or fed into other HMD-compatible tooling without staying in the
R session.
Usage
download_ine_data(
out_dir,
stages = c("births", "deaths", "population", "exposure", "mx", "life_tables"),
format = c("csv", "txt"),
n_periods = 30
)
Arguments
out_dir |
Directory to write into (created if it doesn't exist). |
stages |
Character vector of stages to include. One or more of
|
format |
Character vector, one or both of |
n_periods |
Number of most recent years to fetch for the births/deaths/population retrieval stages. |
Details
Later stages depend on earlier ones (exposure needs population and
deaths; mx needs deaths and exposure; life_tables needs mx).
Requesting a later stage automatically fetches/computes and writes its
dependencies too, since they were already retrieved along the way.
Value
Invisibly, a list with the in-memory results of every stage that
was run (births, deaths, population, exposure, death_rates,
life_tables, each NULL if not run) and files, a character vector
of every path written.
Examples
## Not run:
# Not run: requires live network access to the INE API, and writes files
# to disk.
# Everything, both formats, into ./ine_data
download_ine_data("ine_data")
# Just births and deaths, CSV only
download_ine_data("ine_data", stages = c("births", "deaths"), format = "csv")
# Full pipeline through life tables
download_ine_data("ine_data", stages = "life_tables", n_periods = 40)
## End(Not run)
General fertility rate
Description
Computes the general fertility rate (births per 1,000 women of
reproductive age) per province and year, joining get_ine_births()
and get_ine_population() output.
Usage
general_fertility_rate(births_df, pop_df, age_min = 15L, age_max = 49L)
Arguments
births_df |
Births tibble as returned by |
pop_df |
Population tibble as returned by |
age_min |
Integer, the youngest age counted as reproductive-age
(default |
age_max |
Integer, the oldest age counted as reproductive-age
(default |
Details
GFR improves on crude_birth_rate() by dividing births by the female
population actually at risk of childbearing (age age_min-age_max,
default 15-49) instead of the total population — this removes the
distortion crude_birth_rate() suffers when two provinces have
different age/sex structures (e.g. one with proportionally more
elderly residents) despite similar underlying fertility behavior.
GFR is still not a total fertility rate (TFR): it is a single
aggregate rate over all reproductive-age women, not an age-specific
schedule. For a true TFR, use get_ine_births_by_age() with
age_specific_fertility_rate()/total_fertility_rate() instead.
Value
A tibble with nuts3_code, province_name, year, gfr.
Examples
births <- tibble::tibble(
nuts3_code = "ES111", province_name = "A Coruna", year = 2023, total = 100
)
pop <- tibble::tibble(
nuts3_code = "ES111", year = 2023, age = c(10, 25, 40, 60),
female = c(2000, 2500, 2500, 3000)
)
general_fertility_rate(births, pop)
Retrieve province-level births
Description
Retrieves, cleans, and validates Spanish annual live-birth counts by
province and sex from INE's Tempus3 JSON API, per the SHMD Protocol
(Section 12, Step 1: "Birth Count Assembly"). Unlike get_ine_demog()
(which returns a Total-sex-only province count), this returns
sex-disaggregated counts joined to NUTS-3 codes, suitable as an
HMD-format Births input file - see download_ine_data() to write it to disk.
Usage
get_ine_births(
table_id = 6506,
n_periods = 100,
use_cache = TRUE,
force = FALSE,
cache_dir = NULL
)
Arguments
table_id |
INE Tempus3 table ID. Default |
n_periods |
Number of most recent years to fetch. |
use_cache |
Logical (default |
force |
Logical (default |
cache_dir |
Directory for cached data. Default |
Value
list(data, qc): data is a tibble with columns ine_code,
nuts3_code, nuts2_code, province_name, year, female, male,
total; qc is the output of validate_births().
Examples
## Not run:
# Not run: requires live network access to the INE API.
births <- get_ine_births(n_periods = 30)
births$data
births$qc$issues
# Re-fetch even if a cached copy exists:
births <- get_ine_births(n_periods = 30, force = TRUE)
## End(Not run)
Retrieve province-level births by age of mother
Description
Retrieves, cleans, and validates Spanish annual live-birth counts by
province, single year of age of the mother (15-49, plus the two open
intervals under15/50plus), and sex of the newborn, from INE's raw
Tempus3 JSON API. Unlike get_ine_births() (which has no age-of-mother
breakdown), this is the data source needed for age-specific fertility
rates - see age_specific_fertility_rate(), total_fertility_rate(),
mean_age_at_childbearing(), gross_reproduction_rate(), and
net_reproduction_rate().
Usage
get_ine_births_by_age(
table_id = 6508,
n_periods = 100,
use_cache = TRUE,
force = FALSE,
cache_dir = NULL
)
Arguments
table_id |
INE Tempus3 table ID. Default |
n_periods |
Number of most recent years to fetch. This table has
~6,000 series (province x age x newborn-sex), so fetches are slower
than |
use_cache |
Logical (default |
force |
Logical (default |
cache_dir |
Directory for cached data. Default |
Value
list(data, qc): data is a tibble with columns ine_code,
nuts3_code, nuts2_code, province_name, year, age (integer,
NA for the under15 group), age_group (character: "under15",
"15".."49", "50plus"), female, male, total (births to
mothers of that age, by sex of the newborn); qc is the output of
validate_births_by_age().
Examples
## Not run:
# Not run: requires live network access to the INE API.
births_age <- get_ine_births_by_age(n_periods = 10)
births_age$data
## End(Not run)
Retrieve province-level deaths
Description
Retrieves, cleans, and validates Spanish annual death counts by province
and sex from INE's Tempus3 JSON API, per the SHMD Protocol (Section 12,
Step 1: "Death Count Assembly"). Fetches both an age-less table (for the
national total and a national-vs-provincial reconciliation check) and an
age-specific table (needed by compute_exposure() /
compute_death_rates(), which require D(x,t), not just D(t)).
Usage
get_ine_deaths(
table_id = 6545,
age_table_id = 6547,
n_periods = 100,
use_cache = TRUE,
force = FALSE,
cache_dir = NULL
)
Arguments
table_id |
INE table ID for the age-less (province + sex) series.
Default |
age_table_id |
INE table ID for the age-specific series. Default
|
n_periods |
Number of most recent years to fetch. |
use_cache |
Logical (default |
force |
Logical (default |
cache_dir |
Directory for cached data. Default |
Value
list(data_provinces, data_national, qc, qc_age):
data_provinces is age-specific (ine_code, nuts3_code,
nuts2_code, province_name, year, age, female, male,
total); data_national is Spain's age-less total.
Examples
## Not run:
# Not run: requires live network access to the INE API.
deaths <- get_ine_deaths(n_periods = 30)
deaths$data_provinces
# Re-fetch even if a cached copy exists:
deaths <- get_ine_deaths(n_periods = 30, force = TRUE)
## End(Not run)
Get INE Demographic Data
Description
Retrieves demographic data from INE via the official
ineapir::get_data_table() API wrapper, and tidies it into a data frame
with one row per geography x year and one column per indicator.
Usage
get_ine_demog(
indicator,
geo_level = NULL,
year = NULL,
region = NULL,
sex = "Total",
geometry = FALSE
)
Arguments
indicator |
Character vector of indicator codes (see
|
geo_level |
Character, the geographic level to fetch. Must match the
level at which every requested indicator is actually published (see
|
year |
Numeric or character, the year of data. Default ( |
region |
Optional character vector to subset by region name (regular expressions allowed, matched against the geography name). |
sex |
Character, one of |
geometry |
Logical, join geometries from |
Details
Each indicator is mapped to a real INE table id via the ine_variables
registry (see list_ine_indicators()). Different indicators are only
available at different geographic granularities in INE's source tables
(e.g. population is published by municipality, but births/deaths only
down to province) — all requested indicators must share the same
geo_level, or request them separately.
Value
A tidy tibble with columns GEOID, NAME, year, and one column
per requested indicator; an sf object if geometry = TRUE.
Examples
## Not run:
# Not run: requires live network access to the INE API.
pop_data <- get_ine_demog(indicator = "population_total", year = 2023)
births_deaths <- get_ine_demog(
indicator = c("births_total", "deaths_total"), year = 2023
)
## End(Not run)
Get INE Geographic Data
Description
Retrieves spatial geometries for INE geographic levels via the
mapSpain package, which sources
boundaries from Instituto Geografico Nacional / GISCO. Geometries are
returned with a GEOID column that matches the geographic codes returned
by get_ine_demog(), so the two can be joined directly.
Usage
get_ine_geo(
geo_level = c("municipality", "province"),
region = NULL,
moveCAN = TRUE,
can_gap_km = 60
)
Arguments
geo_level |
Character, one of |
region |
Optional character vector to subset by region name (regular expressions allowed). |
moveCAN |
Logical, shift the Canary Islands next to the mainland for
compact national maps (default |
can_gap_km |
Numeric, the gap in kilometers left between the shifted
Canary Islands and the closest point on the mainland coast (default
|
Value
An sf object with columns GEOID, NAME, and geometry,
projected to ETRS89 / UTM zone 30N (EPSG:25830). When moveCAN = TRUE
and the shift was applied, an sfc rectangle marking the shifted
islands' extent is attached as the "can_box" attribute (used by
plot_ine_map() to draw an inset frame).
Examples
## Not run:
# Not run: requires live network access to fetch boundaries via mapSpain.
prov_geo <- get_ine_geo(geo_level = "province")
mun_geo <- get_ine_geo(geo_level = "municipality", region = "Sevilla")
## End(Not run)
Retrieve province-level population by age and sex
Description
Retrieves, cleans, and validates Spanish January-1st provincial population estimates by single-year age and sex from INE's Padron Municipal Continuo, per the SHMD Protocol (Section 12, Step 3: "Population Estimates"). Covers 1996-present; pre-1996 years require the intercensal survival method applied to the 1981/1991 censuses, which is out of scope here.
Usage
get_ine_population(
table_id = 56945,
n_periods = 30,
use_cache = TRUE,
force = FALSE,
cache_dir = NULL
)
Arguments
table_id |
INE table ID. Default |
n_periods |
Number of most recent years to fetch. |
use_cache |
Logical (default |
force |
Logical (default |
cache_dir |
Directory for cached data. Default |
Details
Some province x age x sex population tables are too large for INE's JSON API and are rejected outright; this function automatically falls back to INE's full CSV bulk export in that case (a larger download, but with no series-count limit).
Value
list(data, qc): data is a tibble with columns ine_code,
nuts3_code, nuts2_code, province_name, year, age, female,
male, total; qc is the output of validate_population().
Examples
## Not run:
# Not run: requires live network access to the INE API.
pop <- get_ine_population(n_periods = 10)
pop$data
# Re-fetch even if a cached copy exists:
pop <- get_ine_population(n_periods = 10, force = TRUE)
## End(Not run)
Gross reproduction rate (GRR)
Description
Computes the gross reproduction rate (expected daughters per woman
over her reproductive lifetime, ignoring mortality) per province and
year, summing age_specific_fertility_rate()'s asfr_female column -
the actual female-newborn-specific rate INE's age-of-mother table
provides, rather than the more common approximation of scaling
total_fertility_rate() by an assumed constant sex ratio at birth.
See net_reproduction_rate() to additionally account for mortality
before/during reproductive age.
Usage
gross_reproduction_rate(asfr_df)
Arguments
asfr_df |
Output of |
Value
A tibble with nuts3_code, province_name, year, grr.
Examples
asfr <- tibble::tibble(
nuts3_code = "ES111", province_name = "A Coruna", year = 2023,
age = c(20, 30), asfr = c(30, 80), asfr_female = c(15, 40)
)
gross_reproduction_rate(asfr)
INE demographic indicator reference table
Description
A registry mapping indicator codes used throughout inedemogR to the real
INE table each is retrieved from via ineapir::get_data_table().
Usage
ine_variables
Format
A tibble with 3 rows and 6 variables:
- indicator
Indicator code, e.g.
"population_total".- name
Short human-readable name.
- description
Longer description of what the indicator measures.
- id_table
INE
idTableidentifier, orNAif not yet wired to a live table.- geo_var
Name of the geographic dimension column returned by
ineapir::get_data_table(..., metanames = TRUE)for this table.- geo_level
Geographic granularity the table is published at (
"municipality"or"province").
Source
Instituto Nacional de Estadistica (INE), "fenomenos demograficos".
Infant mortality rate
Description
Computes the infant mortality rate (deaths under age 1 per 1,000 live
births) per province and year, joining get_ine_deaths() and
get_ine_births() output.
Usage
infant_mortality_rate(deaths_df, births_df)
Arguments
deaths_df |
Deaths tibble as returned by |
births_df |
Births tibble as returned by |
Details
This is the standard demographic IMR: infant deaths in a year divided
by live births in that same year (the birth cohort those deaths are
drawn from), not by population — a different denominator convention
from crude_death_rate(). It is closely related to, but not
identical to, q0 (probability of dying before age 1) in
build_life_table()'s output: q0 is derived from the exposure-based
central death rate m0 via the Andreev-Kingkade a0 (per HMD Methods
Protocol V6), while IMR here uses the simpler, more standard
deaths/births ratio directly. The two will usually be close but need
not match exactly.
Value
A tibble with nuts3_code, province_name, year, imr.
Examples
deaths <- tibble::tibble(
nuts3_code = "ES111", province_name = "A Coruna", year = 2023,
age = c(0, 1, 65), total = c(3, 1, 40)
)
births <- tibble::tibble(nuts3_code = "ES111", year = 2023, total = 1000)
infant_mortality_rate(deaths, births)
Life expectancy at birth and at age 65, for one province
Description
Convenience wrapper for a single province: builds a period life table
(Andreev-Kingkade a0, Kannisto old-age smoothing, per HMD Methods
Protocol V6) from already-computed central death rates and extracts
life expectancy at birth (e0) and at age 65 (e65) for every year
present. Operates on compute_death_rates()'s mx_1x1 output
directly — data already retrieved/computed via the mortality
pipeline — the same way plot_lexis_diagram() does, rather than
requiring build_life_tables() to be run for every province first
and life_expectancy_summary() applied afterwards.
Usage
life_expectancy(mx_df, province, sex = c("total", "female", "male"))
Arguments
mx_df |
Output of the |
province |
Character, a province name (regular expressions
allowed, matched against |
sex |
Character, one of |
Value
A tibble with nuts3_code, province_name, year, e0,
e65, sex.
Examples
# A Gompertz-like mx curve spanning to a realistic terminal age (100):
# build_life_table()'s open-interval formula at the terminal age
# (Lx = lx / mx) assumes that age is genuinely old (high mx), so a
# short age range with a low terminal mx would produce a nonsensical
# "remaining life expectancy" in the thousands of years.
age <- 0:100
mx <- tibble::tibble(
nuts3_code = "ES111", province_name = "A Coruna", year = 2023, age = age,
mx_female = 0.0003 * exp(0.07 * age),
mx_male = 0.00035 * exp(0.072 * age),
mx_total = 0.00033 * exp(0.071 * age)
)
life_expectancy(mx, province = "A Coruna", sex = "female")
Life expectancy summary
Description
Extracts life expectancy at birth (e0) and at age 65 (e65) per
province and year from a build_life_tables() period life table.
Feeds map_life_expectancy(), which bridges this summary with
get_ine_geo()'s province geometries.
Usage
life_expectancy_summary(lt_df, sex = c("female", "male", "both"))
Arguments
lt_df |
One of |
sex |
Character label to attach to the output ( |
Value
A tibble with nuts3_code, province_name, year, e0,
e65, sex.
Examples
lt <- tibble::tibble(
nuts3_code = "ES111", province_name = "A Coruna", year = 2023,
age = c(0, 65), ex = c(86.97, 20.5)
)
life_expectancy_summary(lt, sex = "female")
List Available INE Indicators
Description
Returns a data frame of available demographic indicators.
Usage
list_ine_indicators()
Value
A data frame with indicator codes, names, and descriptions.
Examples
list_ine_indicators()
Map any indicator by province or municipality
Description
General-purpose choropleth: joins a tidy indicator tibble (keyed by
GEOID, matching get_ine_geo()'s output — e.g. get_ine_demog()'s
output already has it) onto province or municipality geometry and
renders it, either as a binned/discrete-legend map (the default,
matching the classic "N provinces above/below a threshold" style of
choropleth) or a continuous gradient. map_life_expectancy() is a
thin wrapper around this function for System B's life-table output.
Usage
map_indicator(
df,
value_col,
geo_level = c("province", "municipality"),
region = NULL,
binned = TRUE,
breaks = NULL,
palette = if (binned) "PiYG" else "D",
moveCAN = TRUE,
can_gap_km = 60,
legend_title = NULL,
title = NULL
)
Arguments
df |
A tibble with a |
value_col |
Character, the name of the numeric column to map. |
geo_level |
Character, one of |
region |
Optional character vector to subset the geometry by
region name (regular expressions allowed). See |
binned |
Logical (default |
breaks |
Numeric vector of bin edges when |
palette |
Character, a |
moveCAN |
Logical, shift the Canary Islands next to the mainland
(default |
can_gap_km |
Numeric, gap in km for the shifted Canary Islands
(default |
legend_title |
Optional legend title (defaults to |
title |
Optional plot title. |
Value
A ggplot object.
Examples
## Not run:
# Not run: get_ine_geo() requires live network access to fetch boundaries.
pop_data <- get_ine_demog(indicator = "population_total", year = 2023)
map_indicator(pop_data, "population_total", geo_level = "province")
## End(Not run)
Map life expectancy by province
Description
Bridges System B's mortality pipeline (build_life_tables() via
life_expectancy_summary()) with System A's spatial layer
(get_ine_geo()) to render a province-level choropleth of life
expectancy at birth. A thin wrapper around map_indicator() (a
continuous gradient, since life expectancy has no natural discrete
bins) that handles the nuts3_code -> GEOID bridge via
province_lookup. See plot_ine_map() for the analogous
region-highlighting map built purely on get_ine_geo().
Usage
map_life_expectancy(
le_df,
year,
sex = "both",
moveCAN = TRUE,
can_gap_km = 60,
title = NULL
)
Arguments
le_df |
Output of |
year |
Numeric, the year to plot. |
sex |
Character, one of |
moveCAN |
Logical, shift the Canary Islands next to the mainland
(default |
can_gap_km |
Numeric, gap in km for the shifted Canary Islands
(default |
title |
Optional plot title. |
Value
A ggplot object.
Examples
## Not run:
# Not run: get_ine_geo() requires live network access to fetch province
# boundaries.
lt <- build_life_tables(rates$mx_1x1)
le <- life_expectancy_summary(lt$fltper, sex = "female")
map_life_expectancy(le, year = max(le$year), sex = "female")
## End(Not run)
Mean age at childbearing (MAC)
Description
Computes the mean age at childbearing (the ASFR-weighted average age
of mothers at birth) per province and year, from
age_specific_fertility_rate() output.
Usage
mean_age_at_childbearing(asfr_df)
Arguments
asfr_df |
Output of |
Value
A tibble with nuts3_code, province_name, year, mac.
Examples
asfr <- tibble::tibble(
nuts3_code = "ES111", province_name = "A Coruna", year = 2023,
age = c(20, 30), asfr = c(30, 80), asfr_female = c(15, 40)
)
mean_age_at_childbearing(asfr)
Net reproduction rate (NRR)
Description
Computes the net reproduction rate (expected daughters per woman over
her reproductive lifetime, accounting for the mother's own survival to
each reproductive age) per province and year, weighting
age_specific_fertility_rate()'s asfr_female by the female
life-table survivorship function Lx from build_life_tables()'s
fltper (person-years lived in the age interval, per HMD Methods
Protocol V6 - the same Lx life_expectancy_summary()'s ex is
derived from). Unlike gross_reproduction_rate(), which assumes every
woman survives to bear children at every age, NRR is the mortality-
adjusted figure: NRR < GRR whenever there is any mortality before the
end of the reproductive span.
Usage
net_reproduction_rate(asfr_df, lt_df)
Arguments
asfr_df |
Output of |
lt_df |
|
Value
A tibble with nuts3_code, province_name, year, nrr.
Examples
asfr <- tibble::tibble(
nuts3_code = "ES111", province_name = "A Coruna", year = 2023,
age = c(20, 30), asfr = c(30, 80), asfr_female = c(15, 40)
)
fltper <- tibble::tibble(
nuts3_code = "ES111", year = 2023, age = c(20, 30), Lx = c(99000, 98500)
)
net_reproduction_rate(asfr, fltper)
Plot a demographic indicator trend over time
Description
Generic time-series line chart for any indicator tibble keyed by
nuts3_code/province_name/year, such as the output of
age_dependency_ratio(), aging_index(), sex_ratio(),
crude_birth_rate(), or life_expectancy_summary().
Usage
plot_demog_trend(df, value_col, region = NULL, title = NULL, ylab = NULL)
Arguments
df |
A tibble with |
value_col |
Character, the name of the column to plot. |
region |
Optional character vector to subset by province name
(regular expressions allowed, matched against |
title |
Optional plot title. |
ylab |
Optional y-axis label (defaults to |
Value
A ggplot object.
Examples
trend <- tibble::tibble(
nuts3_code = "ES111", province_name = "A Coruna",
year = c(2022, 2023), aging_index = c(150, 160)
)
plot_demog_trend(trend, "aging_index")
Plot a Map of Spain with Regions Highlighted
Description
Plots the full map of Spain at the requested geographic level (provinces
or municipalities), with one or more regions highlighted in a different
color. Useful for confirming which regions a region filter passed to
get_ine_demog() or get_ine_geo() actually matches, since
get_ine_geo() uses regex substring matching by default (see
vignette examples in test_cordoba.R).
Usage
plot_ine_map(
geo_level = c("province", "municipality"),
highlight = NULL,
base_color = "grey90",
highlight_color = "firebrick",
title = NULL,
can_box = TRUE,
can_gap_km = 60
)
Arguments
geo_level |
Character, one of |
highlight |
Character vector of region names to highlight (regular
expressions allowed, matched against the geography name — same
matching rules as |
base_color |
Fill color for non-highlighted regions. Default
|
highlight_color |
Fill color for highlighted regions. Default
|
title |
Optional plot title. |
can_box |
Logical, draw an inset separator box around the Canary
Islands, which are shifted next to the mainland for a compact map
(default |
can_gap_km |
Numeric, how close (in km) the shifted Canary Islands
sit next to the mainland (default |
Value
A ggplot object.
Examples
## Not run:
# Not run: get_ine_geo() requires live network access to fetch boundaries.
plot_ine_map(geo_level = "province", highlight = "^Córdoba$")
plot_ine_map(geo_level = "municipality", highlight = "Córdoba")
## End(Not run)
Calculate and plot a Lexis diagram for one province
Description
Builds the classic demographic Lexis surface — age (y-axis) by
calendar year (x-axis), shaded by mortality rate, with birth-cohort
diagonals overlaid — for one province, from the age x year central
death rates already computed by compute_death_rates(). Operates on
data already retrieved/computed via the mortality pipeline
(get_ine_deaths() -> compute_exposure() -> compute_death_rates());
it does not fetch anything itself.
Usage
plot_lexis_diagram(
mx_df,
province,
sex = c("total", "female", "male"),
log_scale = TRUE,
rate_per = 1000,
cohort_lines = TRUE,
cohort_step = 10,
title = NULL
)
Arguments
mx_df |
Output of the |
province |
Character, a province name (regular expressions
allowed, matched against |
sex |
Character, one of |
log_scale |
Logical (default |
rate_per |
Numeric, express the mortality rate as deaths per this
many people (default |
cohort_lines |
Logical (default |
cohort_step |
Numeric, spacing in years between overlaid cohort
diagonals (default |
title |
Optional plot title (defaults to the matched province name). |
Details
"Calculate" here means deriving the tidy age x year surface for the
requested province/sex and the cohort-diagonal positions to overlay
(age = year - cohort, for cohorts every cohort_step years across the
data's range) — not fitting a new mortality model; the rates
themselves come straight from compute_death_rates().
The white diagonal lines are intentional, not an artifact. They
are birth-cohort lines (age = year - cohort): every point along one
line represents the same group of people born in the same year, aging
one year for every calendar year that passes — the defining feature of
a Lexis diagram, letting you trace one cohort's mortality experience
across its lifetime instead of only reading across a fixed year or up
a fixed age. Set cohort_lines = FALSE to turn them off.
Grey cells mean no rate could be computed for that age x year cell, almost always because the source population data has no single-year age breakdown for the oldest ages in the earliest years of the series (so exposure, the rate's denominator, is missing there) — not a bug in the calculation. This typically shows up as a rectangular block in the upper-left (oldest ages, earliest years), clearing up once the source data's age detail becomes complete. When present, grey gets its own "Missing data" legend key (a continuous color scale can't show this on its own, so it's added via a small dummy layer).
Value
A ggplot object.
Examples
mx <- tibble::tibble(
nuts3_code = "ES111", province_name = "A Coruna",
year = rep(2020:2023, each = 3), age = rep(c(0, 50, 90), 4),
mx_total = c(
0.004, 0.003, 0.15, 0.0038, 0.0031, 0.14,
0.0035, 0.0029, 0.16, 0.0033, 0.0028, 0.15
)
)
plot_lexis_diagram(mx, province = "A Coruna")
Plot a population pyramid
Description
Draws a population pyramid for one province and year from
age-disaggregated population data. Requires an age/sex breakdown, so it
operates on get_ine_population()'s output, not get_ine_demog()'s
population_total indicator.
Usage
plot_population_pyramid(pop_df, year, region = NULL, title = NULL)
Arguments
pop_df |
Population tibble as returned by |
year |
Numeric, the year to plot. |
region |
Optional character vector to subset by province name
(regular expressions allowed, matched against |
title |
Optional plot title. |
Value
A ggplot object.
Examples
pop <- tibble::tibble(
province_name = "A Coruna", year = 2023,
age = c(0, 1), female = c(100, 90), male = c(105, 95)
)
plot_population_pyramid(pop, year = 2023)
Rate of natural increase
Description
Computes the rate of natural increase (RNI = CBR - CDR, per 1,000
population) per province and year, combining already-computed
crude_birth_rate() and crude_death_rate() output rather than
re-deriving from raw births/deaths/population — consistent with how
life_expectancy_summary() consumes build_life_tables()'s output
rather than recomputing it.
Usage
rate_of_natural_increase(cbr_df, cdr_df)
Arguments
cbr_df |
Output of |
cdr_df |
Output of |
Value
A tibble with nuts3_code, province_name, year, rni. A
positive value means births outnumber deaths (population growing
from natural change alone, ignoring migration); negative means the
reverse.
Examples
cbr <- tibble::tibble(
nuts3_code = "ES111", province_name = "A Coruna", year = 2023, cbr = 6.5
)
cdr <- tibble::tibble(nuts3_code = "ES111", year = 2023, cdr = 12.3)
rate_of_natural_increase(cbr, cdr)
Sex ratio
Description
Computes the sex ratio (males per 100 females) per province and year
from age-disaggregated population data. Requires the female/male
columns get_ine_population() provides; get_ine_demog()'s
population_total indicator has no sex breakdown and cannot be used
here.
Usage
sex_ratio(pop_df, by_age = FALSE)
Arguments
pop_df |
Population tibble as returned by |
by_age |
Logical, keep the |
Value
A tibble with nuts3_code, province_name, year (and age if
by_age = TRUE), sex_ratio.
Examples
pop <- tibble::tibble(
nuts3_code = "ES111", province_name = "A Coruna", year = 2023,
age = c(0, 1), female = c(100, 95), male = c(105, 100)
)
sex_ratio(pop)
sex_ratio(pop, by_age = TRUE)
Total fertility rate (TFR)
Description
Computes the total fertility rate (expected live births per woman
over her reproductive lifetime, under a given year's fertility
schedule) per province and year, by summing age_specific_fertility_rate()
over single years of age. This is the true TFR that
crude_birth_rate()'s and general_fertility_rate()'s documentation
both note the package previously could not compute, since it requires
the age-of-mother breakdown get_ine_births_by_age() retrieves.
Usage
total_fertility_rate(asfr_df)
Arguments
asfr_df |
Output of |
Value
A tibble with nuts3_code, province_name, year, tfr.
Examples
asfr <- tibble::tibble(
nuts3_code = "ES111", province_name = "A Coruna", year = 2023,
age = c(20, 30), asfr = c(30, 80), asfr_female = c(15, 40)
)
total_fertility_rate(asfr)
Update INE Data
Description
Checks each indicator wired in ine_variables for its latest published
year (via get_ine_demog()) and, if newer than the local cache, downloads
and caches it for offline use.
Usage
update_ine_data(force = FALSE, data_dir)
Arguments
force |
Logical, force update even if data is current. |
data_dir |
Character, directory for cached data. No default: this
function only writes when a directory is explicitly supplied, per CRAN
policy against writing to the user's home filespace by default. Pass
e.g. |
Value
Invisibly, a named list of the latest cached year per indicator.
Examples
## Not run:
# Not run: requires live network access to the INE API, and writes to
# the supplied cache directory.
update_ine_data(data_dir = tools::R_user_dir("inedemogR", "cache"))
## End(Not run)
Validate a constructed abridged life table
Description
Checks: lx strictly non-increasing by age group; Lx > 0; ex > 0; qx in [0, 1]. Mirrors validate_life_table() for the abridged
(5-year age group) case.
Usage
validate_abridged_life_table(alt)
Arguments
alt |
Output of |
Value
list(passed = logical, issues = named list of flagged tibbles).
Examples
mx1 <- data.frame(age = 0:4, mx = c(0.004, 0.0003, 0.0002, 0.0002, 0.0002))
mx5 <- data.frame(
age_group = c("00-04", "05-09", "100+"), mx = c(0.0006, 0.0001, 0.35)
)
alt <- build_abridged_life_table(mx1, mx5, "female")
validate_abridged_life_table(alt)
Validate cleaned provincial birth data
Description
Checks: sex ratio at birth (SRB) implausibly far from the expected value, accounting for sample size; no negative/missing counts; no duplicate province-year rows; continuous year coverage.
Usage
validate_births(df)
Arguments
df |
Output of the |
Details
The SRB check does not use a single fixed band (an earlier version used [1.030, 1.070], which flagged ~60% of all province-years, including 38% of Madrid/Barcelona's — clearly miscalibrated: annual province-level SRB is naturally noisy for small birth counts, and this data's own pooled SRB runs about 1.06, already above that band's upper bound even before any noise). Instead it flags a province-year only if both (a) the observed SRB is statistically implausible given that year's birth count, assuming a true underlying SRB of 1.06 (a two-tailed z-test on the male-birth proportion at z > 4, i.e. roughly a 1-in-16,000 event under the null - deliberately strict, since thousands of province-years are tested at once), and (b) the deviation is also practically meaningful (SRB more than 0.03 from 1.06), so statistically-significant-but-tiny deviations in large provinces aren't flagged just because their sample size makes the test hyper-sensitive. An SRB outside [0.90, 1.25] is additionally always flagged as a sanity floor for gross data errors, but only once total births reach 200: below that, even a large swing (e.g. 23 vs. 17 births) is unremarkable binomial noise, not a data problem, and the z-test above already accounts for the small sample correctly.
Value
list(passed = logical, issues = named list of flagged tibbles).
Examples
births_df <- tibble::tibble(
nuts3_code = c("ES611", "ES611", "ES612", "ES612"),
province_name = c("Almeria", "Almeria", "Cadiz", "Cadiz"),
year = c(2020, 2021, 2020, 2021),
female = c(950, 970, 1200, 1210),
male = c(1000, 1020, 1260, 1270),
total = female + male
)
validate_births(births_df)
Validate cleaned age-of-mother birth data
Description
Checks: no negative/missing counts; no duplicate province-year-age
rows; single-year ages (15-49) present for every province-year found
in the data (the two open intervals, under15/50plus, are not
required to be present since they are typically very small or zero).
Usage
validate_births_by_age(df)
Arguments
df |
Output of the |
Value
list(passed = logical, issues = named list of flagged tibbles).
Examples
# Only 3 of the 35 required single-year ages (15-49) are present here,
# so this deliberately triggers the incomplete age coverage check.
births_age_df <- tibble::tibble(
nuts3_code = "ES611",
province_name = "Almeria",
year = 2020,
age = c(20, 21, 22),
age_group = c("20", "21", "22"),
female = c(30, 28, 25),
male = c(32, 29, 27),
total = female + male
)
validate_births_by_age(births_age_df)
Validate computed central death rates
Description
Checks: no negative/NA/infinite rates; no rates >= 1 for ages below 90 (flagged for review, not treated as a hard error).
Usage
validate_death_rates(mx_df)
Arguments
mx_df |
Output of the |
Value
list(passed = logical, issues = named list of flagged tibbles).
Examples
deaths <- tibble::tibble(
nuts3_code = "ES111", province_name = "A Coruna", year = 2023,
age = c(0, 1), female = c(1, 0), male = c(1, 1), total = c(2, 1)
)
exposure <- tibble::tibble(
nuts3_code = "ES111", province_name = "A Coruna", year = 2023,
age = c(0, 1), female = c(500, 490), male = c(510, 505), total = c(1010, 995)
)
rates <- compute_death_rates(deaths, exposure)
validate_death_rates(rates$mx_1x1)
Validate cleaned provincial death data
Description
Checks: sex ratio at death in [0.90, 1.50]; no negative/missing
counts; no duplicate province-year rows; continuous year coverage;
provincial sum vs. national total (if nat_df supplied).
Usage
validate_deaths(prov_df, nat_df = tibble::tibble())
Arguments
prov_df |
Province-level cleaned deaths tibble. |
nat_df |
National-level cleaned deaths tibble (optional). |
Value
list(passed = logical, issues = named list of flagged tibbles).
Examples
deaths_df <- tibble::tibble(
nuts3_code = c("ES611", "ES611", "ES612", "ES612"),
province_name = c("Almeria", "Almeria", "Cadiz", "Cadiz"),
year = c(2020, 2021, 2020, 2021),
female = c(480, 500, 610, 630),
male = c(510, 520, 640, 655),
total = female + male
)
validate_deaths(deaths_df)
Validate cleaned age-specific provincial death data
Description
Checks: no negative/missing counts; no duplicate province-age-year rows; continuous year coverage per province.
Usage
validate_deaths_age(df)
Arguments
df |
Age-specific province deaths tibble. |
Value
list(passed = logical, issues = named list of flagged tibbles).
Examples
deaths_age_df <- tibble::tibble(
nuts3_code = c("ES611", "ES611"),
province_name = c("Almeria", "Almeria"),
year = c(2020, 2020),
age = c(0, 1),
female = c(2, 0),
male = c(3, 1),
total = female + male
)
validate_deaths_age(deaths_age_df)
Validate computed exposure-to-risk values
Description
Checks: cells with no usable source population (flagged for audit, not treated as an error); no other negative/NA exposures; exposure should not exceed 2x population (a generous plausibility bound).
Usage
validate_exposure(exposure_df, population_df)
Arguments
exposure_df |
Output of the |
population_df |
The population tibble originally passed in. |
Value
list(passed = logical, issues = named list of flagged tibbles).
Examples
exposure_df <- tibble::tibble(
nuts3_code = "ES611", year = 2020, age = c(0, 1),
female = c(495, 480), male = c(520, 500), total = c(1015, 980),
is_boundary_year = FALSE, is_missing_source_pop = FALSE
)
population_df <- tibble::tibble(
nuts3_code = "ES611", year = 2020, age = c(0, 1), total = c(1000, 970)
)
validate_exposure(exposure_df, population_df)
Validate a constructed life table
Description
Checks: lx strictly non-increasing in age; Lx > 0; ex > 0; qx in [0, 1].
Usage
validate_life_table(lt)
Arguments
lt |
Output of |
Value
list(passed = logical, issues = named list of flagged tibbles).
Examples
mx <- data.frame(age = 0:5, mx = c(0.004, 0.0003, 0.0002, 0.0002, 0.0002, 0.0002))
lt <- build_life_table(mx, "female")
validate_life_table(lt)
Validate cleaned provincial population data
Description
Checks: no negative/missing counts; full age range (0..100) present per province-year; no duplicate province-age-year rows; continuous year coverage; no implausible age-to-age jumps (>50%, informational only).
Usage
validate_population(df)
Arguments
df |
Output of the |
Value
list(passed = logical, issues = named list of flagged tibbles).
Examples
population_df <- tibble::tibble(
nuts3_code = c("ES611", "ES611"),
province_name = c("Almeria", "Almeria"),
year = c(2020, 2020),
age = c(0, 1),
female = c(480, 490),
male = c(500, 505),
total = female + male
)
validate_population(population_df)