The gender wage gap in Krabbistan, 1995–2015

A synthetic three-census study inspired by Blau and Kahn (2017)

Author

Krabbs

Published

August 11, 2026

Overview

Krabbistan is a fictional small nation whose labor market is calibrated to be broadly reminiscent of the United States. This report creates census microdata for 1995, 2005, and 2015 and studies the gender wage gap using annual own earnings divided by annual hours.

The analysis follows the organizing logic of Blau and Kahn (2017):

  1. raw mean log-wage gaps overall and by parenthood × marriage;
  2. male-reference Oaxaca–Blinder decompositions of the mean gap, paralleling their Table 4;
  3. decompositions of changes from 1995 into changing characteristics, changing male prices, and changing unexplained gaps, paralleling their Table 5; and
  4. RIF-regression decompositions at the 10th, 50th, and 90th unconditional percentiles, as a rough analogue to their Table 6.

The data are entirely synthetic and the results are pedagogical, not estimates for any real country. The executable analysis is in R because this rendering environment does not contain a licensed Stata runtime. A complete Stata translation is supplied alongside the report.

Show R code
set.seed(42042017)

library(dplyr)
library(tidyr)
library(ggplot2)
library(knitr)
library(scales)

dir.create("data", showWarnings = FALSE)
dir.create("results", showWarnings = FALSE)
dir.create("figures", showWarnings = FALSE)

years <- c(1995L, 2005L, 2015L)
n_per_wave <- 20000L
beta_groups <- list(
  Education = paste0("educ_", 2:5),
  Experience = c("experience", "experience_sq"),
  Industry = paste0("industry_", 2:8),
  Occupation = paste0("occupation_", 2:8)
)

theme_set(theme_minimal(base_size = 12.5))
gap_colors <- c(
  Education = "#56B4E9", Experience = "#E69F00",
  Industry = "#009E73", Occupation = "#CC79A7",
  Unexplained = "#777777"
)

Simulating the census

Each wave contains 20,000 residents ages 18–64. Education rises over time, women overtake men educationally, occupational and industrial segregation decline, women’s labor-force participation rises, and the direct wage penalty attached to being female shrinks. Parenthood and marriage retain additional female wage penalties, although both also diminish.

Show R code
softmax_draw <- function(scores) {
  scores <- scores - apply(scores, 1, max)
  probabilities <- exp(scores)
  probabilities <- probabilities / rowSums(probabilities)
  cumulative <- t(apply(probabilities, 1, cumsum))
  u <- runif(nrow(scores))
  1L + rowSums(u > cumulative)
}

simulate_wave <- function(year, n = n_per_wave) {
  t <- (year - 1995) / 10
  sex <- rbinom(n, 1, 0.505) # 0 male, 1 female

  # Triangular working-age distribution with an early male age advantage.
  age <- round(runif(n, 18, 65) + (1 - sex) * (3.5 - 1.2 * t))
  age <- pmin(64L, pmax(18L, age))

  educ_latent <- rnorm(n) + 0.16 * t + sex * (-0.06 + 0.03 * t) +
    0.010 * (age - 40)
  education <- as.integer(cut(
    educ_latent,
    breaks = c(-Inf, -0.90, -0.20, 0.50, 1.18, Inf),
    labels = FALSE
  ))
  education_years <- c(10, 12, 14, 16, 18)[education]
  college <- education >= 4

  p_married <- plogis(
    -0.15 + 0.105 * (age - 25) - 0.0031 * (age - 41)^2 +
      0.17 * college - 0.10 * sex - 0.10 * t
  )
  married <- rbinom(n, 1, p_married)
  p_former <- plogis(-2.2 + 0.075 * (age - 30) + 0.12 * sex)
  formerly <- married == 0 & runif(n) < p_former
  marital_status <- ifelse(married == 1, 2L, ifelse(formerly, 3L, 1L))

  p_parent <- plogis(
    -1.15 + 0.115 * (age - 24) - 0.0030 * (age - 39)^2 +
      0.72 * married - 0.13 * (education - 3) - 0.05 * t
  )
  parent <- rbinom(n, 1, p_parent)

  edc <- education - 3
  occ_scores <- cbind(
    -0.55 + 0.48 * edc - sex * (0.72 - 0.20 * t),
    -0.75 + 0.70 * edc + sex * (0.12 + 0.03 * t),
    0.05 + 0.18 * edc + sex * (0.45 - 0.09 * t),
    -0.15 + 0.05 * edc + sex * 0.10,
    -0.05 - 0.18 * edc + sex * (0.53 - 0.07 * t),
    -0.35 - 0.08 * edc - sex * (1.15 - 0.16 * t),
    -0.25 - 0.16 * edc - sex * (0.76 - 0.11 * t),
    -0.45 - 0.24 * edc - sex * (0.28 - 0.04 * t)
  )
  occupation <- softmax_draw(occ_scores)

  professional <- occupation %in% 1:3
  manual <- occupation %in% 6:8
  ind_scores <- cbind(
    -0.15 + 0.35 * edc + 0.25 * professional - sex * (0.25 - 0.06 * t),
    -0.10 + 0.22 * edc + sex * (0.65 - 0.08 * t),
    0.05 - 0.12 * edc + 0.38 * manual - sex * (0.50 - 0.08 * t),
    -0.55 - 0.08 * edc + 0.70 * (occupation == 6) - sex * (1.20 - 0.16 * t),
    0.05 - 0.05 * edc + 0.18 * (occupation %in% 3:5),
    -0.35 + 0.42 * edc + 0.20 * professional - sex * (0.18 - 0.04 * t),
    -0.50 + 0.20 * edc + sex * 0.02,
    -0.20 - 0.10 * edc + 0.20 * (occupation == 5) + sex * 0.18
  )
  industry <- softmax_draw(ind_scores)

  potential_experience <- pmax(age - education_years - 6, 0)
  career_break <- sex * parent * (4.0 - 0.75 * t) +
    sex * married * (0.8 - 0.15 * t)
  effective_experience <- pmax(potential_experience - career_break, 0)

  p_lfp <- plogis(
    1.50 - 0.72 * sex + 0.22 * sex * t - 0.48 * sex * parent -
      0.14 * sex * married + 0.16 * (education - 3) -
      0.0035 * (age - 42)^2
  )
  lfp <- rbinom(n, 1, p_lfp)

  educ_premium <- c(0.00, 0.10, 0.22, 0.48, 0.72)[education]
  occ_premium <- c(0.45, 0.38, 0.15, 0.05, -0.15, 0.08, -0.05, -0.15)[occupation]
  ind_premium <- c(0.25, 0.05, 0.12, 0.15, -0.05, 0.30, 0.05, -0.10)[industry]
  base_penalty <- c(`1995` = 0.100, `2005` = 0.090, `2015` = 0.080)[as.character(year)]
  parent_penalty <- c(`1995` = 0.040, `2005` = 0.040, `2015` = 0.040)[as.character(year)]
  married_penalty <- c(`1995` = 0.020, `2005` = 0.020, `2015` = 0.015)[as.character(year)]

  log_hourly_wage <- 2.42 + educ_premium +
    0.045 * effective_experience - 0.00055 * effective_experience^2 +
    occ_premium + ind_premium -
    sex * (base_penalty + parent_penalty * parent + married_penalty * married) +
    rnorm(n, 0, 0.32)
  hourly_wage <- pmin(250, pmax(4, exp(log_hourly_wage)))

  log_hours <- log(1930) - 0.10 * sex - 0.13 * sex * parent -
    0.04 * sex * married + 0.035 * t * sex + rnorm(n, 0, 0.20)
  annual_hours <- ifelse(lfp == 1, round(pmin(3200, pmax(250, exp(log_hours)))), 0)
  own_earnings <- ifelse(lfp == 1, round(hourly_wage * annual_hours), 0)

  data.frame(
    year = as.integer(year), sex = as.integer(sex),
    own_earnings, age = as.integer(age),
    marital_status = as.integer(marital_status), married = as.integer(married),
    parent = as.integer(parent), education = as.integer(education),
    education_years = as.integer(education_years),
    annual_hours = as.integer(annual_hours), lfp = as.integer(lfp),
    industry = as.integer(industry), occupation = as.integer(occupation)
  )
}
Show R code
census <- bind_rows(lapply(years, simulate_wave))

# R-native and portable CSV files are generated directly. Stata-format files
# are written with the recommended foreign package included with R.
saveRDS(census, "data/krabbistan_census_1995_2015.rds")
write.csv(census, "data/krabbistan_census_1995_2015.csv", row.names = FALSE)
foreign::write.dta(census, "data/krabbistan_census_1995_2015.dta", version = 12)
for (yr in years) {
  wave <- census[census$year == yr, ]
  saveRDS(wave, sprintf("data/krabbistan_census_%s.rds", yr))
  foreign::write.dta(wave, sprintf("data/krabbistan_census_%s.dta", yr), version = 12)
}

coverage <- census |>
  group_by(year) |>
  summarise(
    observations = n(), female_share = mean(sex),
    labor_force_participation = mean(lfp),
    mean_age = mean(age), .groups = "drop"
  )
kable(coverage, digits = 3, caption = "Synthetic census coverage")
Synthetic census coverage
year observations female_share labor_force_participation mean_age
1995 20000 0.508 0.554 43.187
2005 20000 0.503 0.592 42.710
2015 20000 0.506 0.621 42.041

The public-use files retain all residents, including zero earnings and zero hours for nonparticipants. The wage analysis restricts attention to ages 25–64, positive earnings, labor-force participation, and at least 500 annual hours. Hourly wages are calculated—not simulated as a released variable—as own earnings divided by annual hours.

Show R code
work <- census |>
  filter(age >= 25, age <= 64, lfp == 1, own_earnings > 0, annual_hours >= 500) |>
  mutate(
    hourly_wage = own_earnings / annual_hours,
    log_wage = log(hourly_wage),
    experience = pmax(age - education_years - 6, 0),
    experience_sq = experience^2
  )

for (j in 2:5) work[[paste0("educ_", j)]] <- as.numeric(work$education == j)
for (j in 2:8) {
  work[[paste0("industry_", j)]] <- as.numeric(work$industry == j)
  work[[paste0("occupation_", j)]] <- as.numeric(work$occupation == j)
}
saveRDS(work, "data/krabbistan_wage_analysis.rds")
foreign::write.dta(work, "data/krabbistan_wage_analysis.dta", version = 12)

Raw wage gaps

Show R code
raw_sex <- work |>
  group_by(year, sex) |>
  summarise(mean_log_wage = mean(log_wage), N = n(), .groups = "drop") |>
  pivot_wider(names_from = sex, values_from = c(mean_log_wage, N), names_prefix = "sex_")

raw_overall <- raw_sex |>
  transmute(
    year,
    male_mean_log_wage = mean_log_wage_sex_0,
    female_mean_log_wage = mean_log_wage_sex_1,
    male_minus_female_log_gap = mean_log_wage_sex_0 - mean_log_wage_sex_1,
    female_male_wage_ratio = exp(mean_log_wage_sex_1 - mean_log_wage_sex_0),
    N = N_sex_0 + N_sex_1
  )

family_sex <- work |>
  group_by(year, parent, married, sex) |>
  summarise(mean_log_wage = mean(log_wage), N = n(), .groups = "drop") |>
  pivot_wider(names_from = sex, values_from = c(mean_log_wage, N), names_prefix = "sex_")

raw_family <- family_sex |>
  mutate(
    family_group = paste0(
      ifelse(parent == 1, "Parent", "Not parent"), " × ",
      ifelse(married == 1, "married", "not married")
    ),
    male_minus_female_log_gap = mean_log_wage_sex_0 - mean_log_wage_sex_1,
    female_male_wage_ratio = exp(mean_log_wage_sex_1 - mean_log_wage_sex_0),
    N = N_sex_0 + N_sex_1
  ) |>
  select(year, parent, married, family_group, male_minus_female_log_gap,
         female_male_wage_ratio, N)

write.csv(raw_overall, "results/raw_gap_overall.csv", row.names = FALSE)
write.csv(raw_family, "results/raw_gap_family.csv", row.names = FALSE)

kable(
  raw_overall |>
    mutate(
      male_minus_female_log_gap = round(male_minus_female_log_gap, 3),
      female_male_wage_ratio = percent(female_male_wage_ratio, accuracy = 0.1)
    ),
  caption = "Raw mean wage gaps"
)
Raw mean wage gaps
year male_mean_log_wage female_mean_log_wage male_minus_female_log_gap female_male_wage_ratio N
1995 3.591023 3.288464 0.303 73.9% 10335
2005 3.618790 3.367863 0.251 77.8% 10883
2015 3.671828 3.476444 0.195 82.3% 11252
Show R code
p_raw <- ggplot(raw_overall, aes(year, male_minus_female_log_gap)) +
  geom_line(linewidth = 1.1, color = "#0072B2") +
  geom_point(size = 3, color = "#0072B2") +
  scale_x_continuous(breaks = years) +
  labs(
    title = "Krabbistan's raw gender wage gap narrows",
    x = "Census year", y = "Male − female mean log wage gap"
  )
p_raw

Show R code
ggsave("figures/raw_gap_over_time.png", p_raw, width = 7.5, height = 4.5, dpi = 180)
Show R code
family_display <- raw_family |>
  transmute(
    year, `Family category` = family_group,
    `Log gap` = round(male_minus_female_log_gap, 3),
    `Female/male wage ratio` = percent(female_male_wage_ratio, accuracy = 0.1),
    N
  )
kable(family_display, caption = "Raw wage gaps by parenthood × marriage")
Raw wage gaps by parenthood × marriage
year Family category Log gap Female/male wage ratio N
1995 Not parent × not married 0.171 84.3% 1235
1995 Not parent × married 0.214 80.8% 1512
1995 Parent × not married 0.309 73.4% 1164
1995 Parent × married 0.328 72.0% 6424
2005 Not parent × not married 0.098 90.6% 1455
2005 Not parent × married 0.171 84.3% 1675
2005 Parent × not married 0.260 77.1% 1224
2005 Parent × married 0.281 75.5% 6529
2015 Not parent × not married 0.108 89.7% 1639
2015 Not parent × married 0.157 85.4% 1804
2015 Parent × not married 0.269 76.4% 1272
2015 Parent × married 0.189 82.8% 6537
Show R code
p_family <- ggplot(
  raw_family,
  aes(year, male_minus_female_log_gap, color = family_group)
) +
  geom_line(linewidth = 1) +
  geom_point(size = 2.6) +
  scale_x_continuous(breaks = years) +
  scale_color_brewer(palette = "Dark2") +
  labs(
    title = "Raw gaps by parenthood and marriage",
    x = "Census year", y = "Male − female mean log wage gap", color = NULL
  ) +
  theme(legend.position = "bottom")
p_family

Show R code
ggsave("figures/raw_gap_family_groups.png", p_family, width = 8.5, height = 5, dpi = 180)

Parents generally have larger gaps because family status affects women’s wage offers, labor-force attachment, and hours more strongly. Married parents have the largest gap in the first two waves; by 2015, compositional selection among working married mothers changes the ordering. The persistent parenthood gradient is more robust than the marriage gradient.

Mean Oaxaca–Blinder decomposition

For year \(t\), let \(\Delta\bar X_t=\bar X_{mt}-\bar X_{ft}\) and let \(\widehat\beta_{mt}\) be the male wage coefficients. The male-reference decomposition is

\[ G_t = \Delta\bar X_t'\widehat\beta_{mt} + U_t, \]

where \(G_t\) is the male–female mean log-wage gap. Group contributions sum the relevant dummy or polynomial terms. The experience proxy is potential experience, \(\max(\text{age}-\text{schooling}-6,0)\), and its square.

Show R code
design_matrix <- function(frame, specification) {
  groups <- c("Education", "Experience")
  if (specification == "Full") groups <- c(groups, "Industry", "Occupation")
  variables <- unlist(beta_groups[groups], use.names = FALSE)
  X <- cbind(`_cons` = 1, as.matrix(frame[, variables, drop = FALSE]))
  list(X = X, variables = c("_cons", variables), groups = groups)
}

fit_ols <- function(y, X) as.numeric(qr.solve(X, y))

table4_rows <- list()
ob_store <- list()
row_id <- 1L

for (yr in years) {
  wave <- work[work$year == yr, ]
  men <- wave[wave$sex == 0, ]
  women <- wave[wave$sex == 1, ]
  gap <- mean(men$log_wage) - mean(women$log_wage)

  for (specification in c("Human capital", "Full")) {
    spec_key <- ifelse(specification == "Full", "Full", "HC")
    dm <- design_matrix(men, spec_key)
    df <- design_matrix(women, spec_key)
    beta <- fit_ols(men$log_wage, dm$X)
    names(beta) <- dm$variables
    dx <- colMeans(dm$X) - colMeans(df$X)
    contributions <- sapply(dm$groups, function(group) {
      variables <- beta_groups[[group]]
      sum(dx[variables] * beta[variables])
    })
    explained <- sum(contributions)
    unexplained <- gap - explained
    ob_store[[paste(yr, specification, sep = "::")]] <- list(
      beta = beta, dx = dx, gap = gap,
      explained = explained, unexplained = unexplained
    )
    values <- c(
      contributions,
      `Total explained` = explained,
      Unexplained = unexplained,
      `Total gap` = gap
    )
    table4_rows[[row_id]] <- data.frame(
      year = yr, specification, component = names(values),
      log_points = as.numeric(values),
      percent_of_gap = 100 * as.numeric(values) / gap
    )
    row_id <- row_id + 1L
  }
}

table4 <- bind_rows(table4_rows)
write.csv(table4, "results/table4_ob_decomposition.csv", row.names = FALSE)

Table 4 analogue

Show R code
table4_display <- table4 |>
  mutate(entry = sprintf("%.3f (%.1f%%)", log_points, percent_of_gap)) |>
  select(specification, component, year, entry) |>
  pivot_wider(names_from = year, values_from = entry)
kable(
  table4_display,
  caption = "Male-reference decomposition: log points (percent of total gap)"
)
Male-reference decomposition: log points (percent of total gap)
specification component 1995 2005 2015
Human capital Education 0.018 (6.1%) -0.004 (-1.8%) -0.004 (-2.0%)
Human capital Experience 0.028 (9.2%) 0.027 (10.6%) 0.016 (8.0%)
Human capital Total explained 0.046 (15.3%) 0.022 (8.9%) 0.012 (5.9%)
Human capital Unexplained 0.256 (84.7%) 0.229 (91.1%) 0.184 (94.1%)
Human capital Total gap 0.303 (100.0%) 0.251 (100.0%) 0.195 (100.0%)
Full Education 0.014 (4.5%) -0.003 (-1.3%) -0.003 (-1.5%)
Full Experience 0.028 (9.2%) 0.027 (10.7%) 0.016 (8.1%)
Full Industry 0.026 (8.7%) 0.020 (7.9%) 0.018 (9.0%)
Full Occupation 0.025 (8.2%) 0.019 (7.7%) 0.014 (7.4%)
Full Total explained 0.092 (30.5%) 0.063 (24.9%) 0.045 (23.1%)
Full Unexplained 0.210 (69.5%) 0.188 (75.1%) 0.150 (76.9%)
Full Total gap 0.303 (100.0%) 0.251 (100.0%) 0.195 (100.0%)
Show R code
table4_plot_data <- table4 |>
  filter(
    specification == "Full",
    component %in% c("Education", "Experience", "Industry", "Occupation", "Unexplained")
  ) |>
  mutate(component = factor(
    component,
    levels = c("Education", "Experience", "Industry", "Occupation", "Unexplained")
  ))

p_table4 <- ggplot(table4_plot_data, aes(factor(year), log_points, fill = component)) +
  geom_col(width = 0.68) +
  scale_fill_manual(values = gap_colors) +
  labs(
    title = "Full Oaxaca–Blinder decomposition of the mean gap",
    x = "Census year", y = "Log points", fill = NULL
  ) +
  theme(legend.position = "bottom")
p_table4

Show R code
ggsave("figures/table4_stacked_components.png", p_table4, width = 8.5, height = 5, dpi = 180)

Education contributes little because women’s schooling catches up and then surpasses men’s. Industry and especially occupation remain important sorting margins. The unexplained component includes the simulated direct gender penalty, unmeasured career interruptions, family penalties, and sampling noise; it must not be interpreted mechanically as discrimination alone.

Change decomposition relative to 1995

Blau and Kahn’s Table 5 emphasizes that the change in the gap depends on both changing gender differences in characteristics and changing prices. Two exact paths are reported. With 1995 coefficients as the base,

\[ G_t-G_{95} = (\Delta\bar X_t-\Delta\bar X_{95})'\widehat\beta_{m,95} +\Delta\bar X_t'(\widehat\beta_{mt}-\widehat\beta_{m,95}) +(U_t-U_{95}). \]

The alternative evaluates mean changes at current coefficients and coefficient changes at the 1995 characteristic gap.

Show R code
table5_rows <- list()
row_id <- 1L

for (specification in c("Human capital", "Full")) {
  base <- ob_store[[paste(1995, specification, sep = "::")]]
  active_groups <- if (specification == "Full") names(beta_groups) else c("Education", "Experience")

  for (yr in c(2005L, 2015L)) {
    current <- ob_store[[paste(yr, specification, sep = "::")]]
    for (path in c("1995 coefficients / current gaps", "Current coefficients / 1995 gaps")) {
      group_rows <- lapply(active_groups, function(group) {
        variables <- beta_groups[[group]]
        dx0 <- base$dx[variables]
        dxt <- current$dx[variables]
        b0 <- base$beta[variables]
        bt <- current$beta[variables]
        if (startsWith(path, "1995")) {
          means <- sum((dxt - dx0) * b0)
          coefficients <- sum(dxt * (bt - b0))
        } else {
          means <- sum((dxt - dx0) * bt)
          coefficients <- sum(dx0 * (bt - b0))
        }
        data.frame(
          year = yr, specification, path, component = group,
          changing_means = means, changing_coefficients = coefficients
        )
      })
      group_rows <- bind_rows(group_rows)
      extras <- data.frame(
        year = yr, specification, path,
        component = c("All covariates", "Unexplained gap", "Total gap change"),
        changing_means = c(
          sum(group_rows$changing_means),
          current$unexplained - base$unexplained,
          current$gap - base$gap
        ),
        changing_coefficients = c(sum(group_rows$changing_coefficients), NA, NA)
      )
      table5_rows[[row_id]] <- bind_rows(group_rows, extras)
      row_id <- row_id + 1L
    }
  }
}

table5 <- bind_rows(table5_rows)
write.csv(table5, "results/table5_changes_from_1995.csv", row.names = FALSE)

Table 5 analogue

Show R code
table5_display <- table5 |>
  filter(specification == "Full") |>
  mutate(
    `Changing means` = ifelse(is.na(changing_means), "", sprintf("%.3f", changing_means)),
    `Changing coefficients` = ifelse(
      is.na(changing_coefficients), "", sprintf("%.3f", changing_coefficients)
    )
  ) |>
  select(year, path, component, `Changing means`, `Changing coefficients`)
kable(table5_display, caption = "Contributions to the change in the gap relative to 1995: full specification")
Contributions to the change in the gap relative to 1995: full specification
year path component Changing means Changing coefficients
2005 1995 coefficients / current gaps Education -0.017 0.001
2005 1995 coefficients / current gaps Experience -0.002 0.001
2005 1995 coefficients / current gaps Industry -0.005 -0.002
2005 1995 coefficients / current gaps Occupation -0.007 0.001
2005 1995 coefficients / current gaps All covariates -0.031 0.001
2005 1995 coefficients / current gaps Unexplained gap -0.022
2005 1995 coefficients / current gaps Total gap change -0.052
2005 Current coefficients / 1995 gaps Education -0.017 -0.000
2005 Current coefficients / 1995 gaps Experience -0.002 0.001
2005 Current coefficients / 1995 gaps Industry -0.005 -0.002
2005 Current coefficients / 1995 gaps Occupation -0.007 0.001
2005 Current coefficients / 1995 gaps All covariates -0.030 0.000
2005 Current coefficients / 1995 gaps Unexplained gap -0.022
2005 Current coefficients / 1995 gaps Total gap change -0.052
2015 1995 coefficients / current gaps Education -0.016 0.000
2015 1995 coefficients / current gaps Experience -0.012 -0.000
2015 1995 coefficients / current gaps Industry -0.008 -0.000
2015 1995 coefficients / current gaps Occupation -0.011 0.001
2015 1995 coefficients / current gaps All covariates -0.047 -0.000
2015 1995 coefficients / current gaps Unexplained gap -0.060
2015 1995 coefficients / current gaps Total gap change -0.107
2015 Current coefficients / 1995 gaps Education -0.016 -0.001
2015 Current coefficients / 1995 gaps Experience -0.011 -0.001
2015 Current coefficients / 1995 gaps Industry -0.008 -0.000
2015 Current coefficients / 1995 gaps Occupation -0.011 0.000
2015 Current coefficients / 1995 gaps All covariates -0.046 -0.001
2015 Current coefficients / 1995 gaps Unexplained gap -0.060
2015 Current coefficients / 1995 gaps Total gap change -0.107
Show R code
means_plot <- table5 |>
  filter(
    specification == "Full",
    path == "1995 coefficients / current gaps",
    component %in% names(beta_groups)
  ) |>
  transmute(year, component = paste("Means:", component), contribution = changing_means)

other_plot <- table5 |>
  filter(
    specification == "Full",
    path == "1995 coefficients / current gaps",
    component %in% c("All covariates", "Unexplained gap")
  ) |>
  transmute(
    year,
    component = ifelse(component == "All covariates", "All coefficient changes", "Unexplained-gap change"),
    contribution = ifelse(component == "All coefficient changes", changing_coefficients, changing_means)
  )

table5_plot <- bind_rows(means_plot, other_plot)
p_table5 <- ggplot(table5_plot, aes(factor(year), contribution, fill = component)) +
  geom_col(width = 0.68) +
  geom_hline(yintercept = 0, linewidth = 0.4) +
  labs(
    title = "Why the gap changed relative to 1995",
    subtitle = "1995-coefficient/current-characteristic-gap path",
    x = "Ending census year", y = "Contribution to change in log gap", fill = NULL
  ) +
  theme(legend.position = "bottom")
p_table5

Show R code
ggsave("figures/table5_stacked_changes.png", p_table5, width = 8.8, height = 5.2, dpi = 180)

Negative bars narrow the gap. The two paths allocate interactions between changing characteristics and changing coefficients differently, but both sum to the same observed gap change once the unexplained component is included.

Distributional decomposition: Table 6 analogue

The original paper uses the Chernozhukov–Fernández-Val–Melly distribution-regression framework. Here, a deliberately rougher recentered-influence-function (RIF) approximation is used. For percentile \(p\), each sex-specific wage is transformed to

\[ \operatorname{RIF}(Y;q_p)=q_p+\frac{p-\mathbf{1}\{Y\le q_p\}}{f_Y(q_p)}, \]

where \(f_Y(q_p)\) is estimated with a Gaussian kernel. Separate male and female RIF regressions then yield an Oaxaca-style covariate effect and wage-coefficient effect at each unconditional percentile.

Show R code
rif_values <- function(y, p) {
  q <- as.numeric(quantile(y, p, names = FALSE, type = 7))
  h <- max(1.06 * sd(y) * length(y)^(-1 / 5), 1e-4)
  density <- mean(dnorm((y - q) / h) / h)
  list(rif = q + (p - as.numeric(y <= q)) / density, quantile = q)
}

table6_rows <- list()
row_id <- 1L
for (yr in years) {
  wave <- work[work$year == yr, ]
  men <- wave[wave$sex == 0, ]
  women <- wave[wave$sex == 1, ]
  for (p in c(0.10, 0.50, 0.90)) {
    rm <- rif_values(men$log_wage, p)
    rf <- rif_values(women$log_wage, p)
    for (specification in c("Human capital", "Full")) {
      key <- ifelse(specification == "Full", "Full", "HC")
      dm <- design_matrix(men, key)
      df <- design_matrix(women, key)
      bm <- fit_ols(rm$rif, dm$X)
      bf <- fit_ols(rf$rif, df$X)
      covariate <- sum((colMeans(dm$X)[-1] - colMeans(df$X)[-1]) * bm[-1])
      coefficient <- sum(colMeans(df$X) * (bm - bf))
      table6_rows[[row_id]] <- data.frame(
        year = yr, percentile = as.integer(100 * p), specification,
        covariate_effect = covariate,
        coefficient_effect = coefficient,
        sum_effects = covariate + coefficient,
        raw_quantile_gap = rm$quantile - rf$quantile
      )
      row_id <- row_id + 1L
    }
  }
}

table6 <- bind_rows(table6_rows)
write.csv(table6, "results/table6_rif_quantile_decomposition.csv", row.names = FALSE)
Show R code
table6_display <- table6 |>
  mutate(across(
    c(covariate_effect, coefficient_effect, sum_effects, raw_quantile_gap),
    ~ round(.x, 3)
  ))
kable(table6_display, caption = "RIF-regression decomposition by unconditional wage percentile")
RIF-regression decomposition by unconditional wage percentile
year percentile specification covariate_effect coefficient_effect sum_effects raw_quantile_gap
1995 10 Human capital 0.042 0.242 0.284 0.284
1995 10 Full 0.085 0.200 0.284 0.284
1995 50 Human capital 0.048 0.252 0.300 0.300
1995 50 Full 0.095 0.205 0.300 0.300
1995 90 Human capital 0.050 0.288 0.338 0.337
1995 90 Full 0.110 0.227 0.338 0.337
2005 10 Human capital 0.025 0.196 0.221 0.221
2005 10 Full 0.064 0.158 0.221 0.221
2005 50 Human capital 0.020 0.230 0.250 0.250
2005 50 Full 0.068 0.182 0.250 0.250
2005 90 Human capital 0.024 0.263 0.287 0.287
2005 90 Full 0.059 0.228 0.287 0.287
2015 10 Human capital 0.012 0.177 0.189 0.189
2015 10 Full 0.041 0.148 0.189 0.189
2015 50 Human capital 0.013 0.185 0.198 0.198
2015 50 Full 0.048 0.150 0.198 0.198
2015 90 Human capital 0.009 0.176 0.185 0.185
2015 90 Full 0.046 0.138 0.185 0.185
Show R code
table6_plot <- table6 |>
  select(year, percentile, specification, covariate_effect, coefficient_effect) |>
  pivot_longer(
    c(covariate_effect, coefficient_effect),
    names_to = "effect", values_to = "log_points"
  ) |>
  mutate(
    effect = recode(
      effect,
      covariate_effect = "Covariates",
      coefficient_effect = "Wage coefficients"
    ),
    cell = paste0(year, "\np", percentile)
  )

p_table6 <- ggplot(table6_plot, aes(cell, log_points, fill = effect)) +
  geom_col(width = 0.72) +
  facet_wrap(~ specification, nrow = 1) +
  scale_fill_manual(values = c(Covariates = "#0072B2", `Wage coefficients` = "#D55E00")) +
  labs(
    title = "RIF approximation to Blau–Kahn Table 6",
    x = "Year and unconditional percentile", y = "Log-point contribution", fill = NULL
  ) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1), legend.position = "bottom")
p_table6

Show R code
ggsave("figures/table6_rif_stacked.png", p_table6, width = 11, height = 5.5, dpi = 180)

The percentile results separate compositional sorting from differences in the wage structure. Because RIF regression is a local linear approximation, sum_effects need not equal the raw sample quantile gap exactly. Standard errors are omitted; a substantive application should bootstrap the entire quantile, density, and regression procedure.

Where the design is feasible in IPUMS International

The IPUMS International sample catalogue and harmonized-variable documentation were audited on 11 August 2026 to identify real-data settings for the same exercise. A direct match must have (i) at least two census microdata samples whose endpoints are at least ten years apart, (ii) the demographic, earnings, education, employment, industry, and occupation variables below in each qualifying wave, and (iii) at least 100,000 person records in each wave. The record threshold is an analytical rule used here, not an IPUMS standard; it leaves ample scope for employed-sex and family-status cells after sample restrictions.

The hours requirement is deliberately flexible. A series passes if it supports at least one of three wage-sample constructions:

  1. Computed hourly wage: earnings divided by exact usual or actual hours (HRSWORK1, HRSUSUAL1, HRSMAIN, or HRSACTUAL1), after aligning reference periods;
  2. Reported hourly wage: a wage rate reported directly in hourly units, without dividing earnings by hours; or
  3. Full-time earnings sample: wage earnings analyzed only among workers identifiable as full-time, using HRSFULL or a source variable with a documented full-time threshold.

Route 3 estimates an earnings gap among full-time workers, not a literal hourly-wage gap. It is therefore a useful fallback but not estimand-equivalent to routes 1 or 2.

Show R code
ipums_crosswalk <- tibble::tribble(
  ~Krabbistan_measure, ~IPUMS_variable, ~Interpretation,
  "Sex", "SEX", "Reported sex",
  "Own earnings", "INCWAGE or INCEARN", "Wage-and-salary income, or broader earned income when the former is unavailable",
  "Age", "AGE", "Age in years",
  "Marital status", "MARST", "Harmonized marital status",
  "Parenthood", "NCHILD/MOMLOC/POPLOC; CHBORN/CHSURV/LASTBYR", "Co-resident parent for both sexes; fertility-history proxy for women",
  "Education", "EDATTAIN", "Internationally harmonized attainment",
  "Wage denominator/sample", "HRSWORK1, HRSUSUAL1, HRSMAIN, HRSACTUAL1, or HRSFULL", "Exact hours, a direct hourly rate, or a documented full-time indicator",
  "Labor-force status", "EMPSTAT", "Employment status",
  "Industry", "INDGEN", "Coarse general industry",
  "Occupation", "OCCISCO", "ISCO-harmonized occupation"
)

kable(
  ipums_crosswalk,
  col.names = c("Krabbistan measure", "IPUMS field", "Interpretation"),
  caption = "Crosswalk used in the feasibility screen"
)
Crosswalk used in the feasibility screen
Krabbistan measure IPUMS field Interpretation
Sex SEX Reported sex
Own earnings INCWAGE or INCEARN Wage-and-salary income, or broader earned income when the former is unavailable
Age AGE Age in years
Marital status MARST Harmonized marital status
Parenthood NCHILD/MOMLOC/POPLOC; CHBORN/CHSURV/LASTBYR Co-resident parent for both sexes; fertility-history proxy for women
Education EDATTAIN Internationally harmonized attainment
Wage denominator/sample HRSWORK1, HRSUSUAL1, HRSMAIN, HRSACTUAL1, or HRSFULL Exact hours, a direct hourly rate, or a documented full-time indicator
Labor-force status EMPSTAT Employment status
Industry INDGEN Coarse general industry
Occupation OCCISCO ISCO-harmonized occupation

Reconstructing parenthood

NCHILD is not essential. The preferred replacement is a co-resident-parent indicator constructed by reversing the IPUMS parent pointers: a person is a parent if another household member’s MOMLOC or POPLOC equals that person’s PERNUM. This has the same conceptual limitation as NCHILD—children outside the household are missed—but it works symmetrically for women and men. Where pointers are unavailable, household relationship and spouse links can often identify children of the head or spouse, though they miss more complex families.

Fertility histories provide a second route. CHBORN > 0, CHSURV > 0, or a valid LASTBYR identifies women who have ever had a birth. These variables capture nonresident children but usually apply only to women, sometimes only within a restricted age range. They therefore cannot by themselves define the same parent category for men and women. The recommended design uses co-resident parenthood as the common main measure and women’s fertility history as a sensitivity check.

Removing NCHILD as a hard screen and admitting INCEARN (total own labor income) materially expands the usable set. Brazil, Jamaica, Mexico, the United States, and Venezuela support repeated-census analyses with a common parent construct; Canada is conditionally usable with a source-level relationship reconstruction or an asymmetric fertility-history sensitivity analysis. Puerto Rico is a technical match but a U.S. territory. Brazil, Mexico, and Venezuela use broader labor earnings rather than wage-and-salary income alone, so their estimand includes self-employment income.

Show R code
ipums_feasibility <- tibble::tribble(
  ~jurisdiction, ~assessment, ~samples, ~minimum_records, ~parent_route, ~wage_status,
  "Brazil", "Feasible; broader earnings", "1991, 2000, 2010 censuses", "17,045,712", "Co-resident links; CHBORN sensitivity", "INCEARN / exact hours; includes business and farm income",
  "Canada", "Conditional", "1981, 1991, 2001 censuses", "486,875", "CHBORN for women; source relationship reconstruction needed for a sex-symmetric measure", "INCWAGE / exact hours or full-time restriction",
  "Jamaica", "Feasible", "1982, 1991, 2001 censuses", "205,179", "Co-resident links; CHBORN sensitivity", "INCWAGE / exact hours",
  "Mexico", "Feasible; broader earnings", "1990, 2000, 2010 censuses", "8,118,242", "Co-resident links; CHBORN sensitivity", "INCEARN / exact hours; includes self-employment income",
  "United States", "Feasible", "1980, 1990, 2000 censuses", "11,343,120", "Co-resident links; CHBORN available through 1990", "INCWAGE / exact hours",
  "Venezuela", "Feasible; broader earnings", "1981 and 2001 censuses", "1,441,266", "Co-resident links; CHBORN available in 2001", "INCEARN / exact hours; 20-year endpoint comparison",
  "Puerto Rico", "Technical match; territory", "1990 and 2000 censuses", "177,655", "Co-resident links; CHBORN in 1990", "INCWAGE / exact hours"
)

write.csv(
  ipums_feasibility,
  "results/ipums_international_feasibility.csv",
  row.names = FALSE
)

kable(
  ipums_feasibility,
  col.names = c(
    "Country or territory", "Assessment", "Potential waves",
    "Minimum IPUMS records", "Parent construction", "Wage construction/deviation"
  ),
  caption = "Repeated-census settings that can support the analysis after flexible parent construction"
)
Repeated-census settings that can support the analysis after flexible parent construction
Country or territory Assessment Potential waves Minimum IPUMS records Parent construction Wage construction/deviation
Brazil Feasible; broader earnings 1991, 2000, 2010 censuses 17,045,712 Co-resident links; CHBORN sensitivity INCEARN / exact hours; includes business and farm income
Canada Conditional 1981, 1991, 2001 censuses 486,875 CHBORN for women; source relationship reconstruction needed for a sex-symmetric measure INCWAGE / exact hours or full-time restriction
Jamaica Feasible 1982, 1991, 2001 censuses 205,179 Co-resident links; CHBORN sensitivity INCWAGE / exact hours
Mexico Feasible; broader earnings 1990, 2000, 2010 censuses 8,118,242 Co-resident links; CHBORN sensitivity INCEARN / exact hours; includes self-employment income
United States Feasible 1980, 1990, 2000 censuses 11,343,120 Co-resident links; CHBORN available through 1990 INCWAGE / exact hours
Venezuela Feasible; broader earnings 1981 and 2001 censuses 1,441,266 Co-resident links; CHBORN available in 2001 INCEARN / exact hours; 20-year endpoint comparison
Puerto Rico Technical match; territory 1990 and 2000 censuses 177,655 Co-resident links; CHBORN in 1990 INCWAGE / exact hours

Twenty-country longlist and the binding constraint

The broader audit produces a longlist of 21 sovereign countries, plus Puerto Rico. All have large IPUMS samples and some substantial portion of the desired demographic/labor design. It is not honest, however, to label all twenty-one feasible wage-gap settings: once parenthood is reconstructed, the binding limitation is repeated individual earnings, not children. The table makes those deviations explicit instead of silently changing the estimand to household income or occupation-imputed wages.

Show R code
ipums_longlist <- tibble::tribble(
  ~country, ~candidate_censuses, ~minimum_records, ~parent_option, ~status_or_blocker,
  "Brazil", "1991/2000/2010", "17,045,712", "Resident child links; fertility history", "Feasible with broader earned income",
  "Canada", "1981/1991/2001", "486,875", "Fertility history; source relationship reconstruction", "Conditional: common male/female parent proxy needs source work",
  "Jamaica", "1982/1991/2001", "205,179", "Resident child links; fertility history", "Feasible",
  "Mexico", "1990/2000/2010", "8,118,242", "Resident child links; fertility history", "Feasible with broader earned income",
  "United States", "1980/1990/2000", "11,343,120", "Resident child links; fertility history", "Feasible",
  "Venezuela", "1981/2001", "1,441,266", "Resident child links; fertility history", "Feasible with broader earned income",
  "Indonesia", "1980/1990 censuses", "912,544", "Resident child links; fertility history", "Censuses lack earnings; 1976/1995 surveys are usable alternatives",
  "Panama", "1990/2000/2010", "232,737", "Resident child links; fertility history", "Earnings present; qualifying waves lack hours/full-time route",
  "Israel", "1983/1995/2008", "403,474", "Resident links through 1995; fertility history", "Earnings present; no repeated hours/full-time route",
  "Trinidad and Tobago", "1980/1990/2000/2011", "105,464", "Resident child links; fertility history", "Individual earnings only in 2000",
  "Uruguay", "1975/1985/1996/2011", "279,994", "Resident child links; fertility history", "Individual wage income only in the 2006 household survey",
  "Switzerland", "1970/1980/1990/2000", "312,538", "Resident child links; fertility history in 2000", "No individual earnings measure",
  "Ecuador", "1990/2001/2010", "966,234", "Resident child links; fertility history", "No individual earnings measure",
  "Spain", "2001/2011", "2,039,274", "Resident child links; earlier fertility history", "No individual earnings measure",
  "France", "1990/1999/2006/2011", "2,360,854", "Resident child links", "No individual earnings measure",
  "Greece", "1991/2001/2011", "969,407", "Resident child links; fertility history", "No individual earnings measure",
  "Italy", "2001/2011", "2,968,065", "Resident child links", "No census individual earnings measure",
  "Mauritius", "1990/2000/2011", "106,710", "Resident child links; fertility history", "No individual earnings measure",
  "Nicaragua", "1995/2005", "435,728", "Resident child links; fertility history", "No individual earnings measure",
  "El Salvador", "1992/2007", "510,760", "Resident child links; fertility history", "No individual earnings measure",
  "South Africa", "1996/2001/2011", "3,621,164", "Resident child links; fertility history", "Excellent labor covariates, but IPUMS provides household—not own—income in these waves",
  "Puerto Rico", "1990/2000", "177,655", "Resident child links; fertility history", "Feasible, but a U.S. territory"
)

write.csv(ipums_longlist, "results/ipums_twenty_country_longlist.csv", row.names = FALSE)

kable(
  ipums_longlist,
  col.names = c(
    "Country or territory", "Candidate census years", "Minimum records",
    "Parent option", "Assessment or binding blocker"
  ),
  caption = "Expanded IPUMS International longlist: 21 sovereign countries plus Puerto Rico"
)
Expanded IPUMS International longlist: 21 sovereign countries plus Puerto Rico
Country or territory Candidate census years Minimum records Parent option Assessment or binding blocker
Brazil 1991/2000/2010 17,045,712 Resident child links; fertility history Feasible with broader earned income
Canada 1981/1991/2001 486,875 Fertility history; source relationship reconstruction Conditional: common male/female parent proxy needs source work
Jamaica 1982/1991/2001 205,179 Resident child links; fertility history Feasible
Mexico 1990/2000/2010 8,118,242 Resident child links; fertility history Feasible with broader earned income
United States 1980/1990/2000 11,343,120 Resident child links; fertility history Feasible
Venezuela 1981/2001 1,441,266 Resident child links; fertility history Feasible with broader earned income
Indonesia 1980/1990 censuses 912,544 Resident child links; fertility history Censuses lack earnings; 1976/1995 surveys are usable alternatives
Panama 1990/2000/2010 232,737 Resident child links; fertility history Earnings present; qualifying waves lack hours/full-time route
Israel 1983/1995/2008 403,474 Resident links through 1995; fertility history Earnings present; no repeated hours/full-time route
Trinidad and Tobago 1980/1990/2000/2011 105,464 Resident child links; fertility history Individual earnings only in 2000
Uruguay 1975/1985/1996/2011 279,994 Resident child links; fertility history Individual wage income only in the 2006 household survey
Switzerland 1970/1980/1990/2000 312,538 Resident child links; fertility history in 2000 No individual earnings measure
Ecuador 1990/2001/2010 966,234 Resident child links; fertility history No individual earnings measure
Spain 2001/2011 2,039,274 Resident child links; earlier fertility history No individual earnings measure
France 1990/1999/2006/2011 2,360,854 Resident child links No individual earnings measure
Greece 1991/2001/2011 969,407 Resident child links; fertility history No individual earnings measure
Italy 2001/2011 2,968,065 Resident child links No census individual earnings measure
Mauritius 1990/2000/2011 106,710 Resident child links; fertility history No individual earnings measure
Nicaragua 1995/2005 435,728 Resident child links; fertility history No individual earnings measure
El Salvador 1992/2007 510,760 Resident child links; fertility history No individual earnings measure
South Africa 1996/2001/2011 3,621,164 Resident child links; fertility history Excellent labor covariates, but IPUMS provides household—not own—income in these waves
Puerto Rico 1990/2000 177,655 Resident child links; fertility history Feasible, but a U.S. territory

This expanded screen also clarifies why India is not in the census longlist: its income-bearing IPUMS files are employment surveys, not census microdata. Mexico has both survey and census material, but the census sequence itself is usable through INCEARN.

South Africa is indeed a strong candidate for the employment and child-penalty parts of the project. IPUMS supplies the 1996, 2001, and 2011 censuses, millions of observations, parent links and fertility histories, schooling, labor-force status, and industry/occupation (through 2007 in the harmonized series). The available income fields for these census samples are household income or household-head income, not the worker’s own earnings. Household income is mechanically contaminated by partners’ earnings and cannot serve as the dependent variable in an individual Oaxaca–Blinder gender-pay decomposition. South Africa should therefore remain on the longlist, with another microdata source required for the wage portion.

Child Penalty Atlas source audit

Kleven, Landais, and Leite-Mariante’s Child Penalty Atlas covers 134 countries. Its core outcome is employment, so inclusion in the Atlas does not imply that its cited file contains own earnings, hours, education, occupation, and industry. The following audit starts from Appendix Table A.1 and asks whether the cited source could support the richer gender-pay analysis here. “Accessible” includes free registration or a research-use application; it does not mean unrestricted anonymous download.

Show R code
atlas_source_text <- "country|source|years
Afghanistan|DHS|2015
Albania|DHS|2008-2017
Algeria|MICS|2012-2019
Angola|Census|2014
Argentina|IPUMS|1970-2001
Armenia|IPUMS|2001-2011
Australia|Panel Data|2001-2019
Austria|Panel Data|1981-2017
Bangladesh|IPUMS|1991-2011
Belarus|IPUMS|1999-2009
Belgium|LIS|1985-2017
Benin|IPUMS|1979-2013
Bolivia|IPUMS|1976-2001
Botswana|IPUMS|1991-2011
Brazil|IPUMS|1991-2010
Bulgaria|SILC|2007-2020
Burkina Faso|IPUMS|1996-2006
Burundi|DHS|2010-2016
Cambodia|IPUMS|1998-2008
Cameroon|IPUMS|1976-2005
Canada|IPUMS|2011
Chad|DHS|1996-2014
Chile|LIS|1990-2017
China|Mini Census|2005
Colombia|IPUMS|1973-2005
Congo, Dem. Rep.|DHS|2007-2013
Congo, Rep.|DHS|2005-2011
Costa Rica|IPUMS|1973-2011
Cote d'Ivoire|LIS|2002-2015
Croatia|SILC|2010-2020
Cuba|IPUMS|2002-2012
Cyprus|SILC|2009-2020
Czech Republic|LIS|1992-2016
Denmark|Panel Data|1980-2017
Dominican Rep.|IPUMS|1981-2010
Ecuador|IPUMS|1982-2010
Egypt|IPUMS|1996-2006
El Salvador|IPUMS|1992-2007
Estonia|SILC|2009-2020
Ethiopia|DHS|2000-2016
Fiji|IPUMS|1976-2014
Finland|SILC|2009-2020
France|LFS|1990-2020
Gabon|DHS|2000-2012
Gambia|LFS|2010-2015
Georgia|LFS|2020-2021
Germany|LIS|1989-2005
Ghana|IPUMS|2000-2010
Greece|IPUMS|1981-2001
Guatemala|IPUMS|1964-2002
Guinea|IPUMS|1983-2014
Guyana|LFS|2017-2021
Haiti|IPUMS|1971-2003
Honduras|IPUMS|1974-2001
Hungary|IPUMS|1990-2011
Iceland|SILC|2004-2018
India|DHS|2005-2015
Indonesia|IPUMS|1971-2010
Iran|IPUMS|2006
Iraq|IPUMS|1997
Ireland|LIS|1994-2018
Israel|LIS|1986-2013
Italy|LIS|1986-2020
Jamaica|IPUMS|1982-2001
Japan|Panel Data|2004-2020
Jordan|IPUMS|2004
Kenya|IPUMS|1989-2009
Kyrgyz Republic|DHS|1997-2012
Laos|IPUMS|2005
Latvia|SILC|2009-2020
Lesotho|IPUMS|1996-2006
Liberia|IPUMS|2008
Lithuania|LIS|2009-2018
Luxembourg|LIS|1985-2013
Madagascar|DHS|1992-2008
Malawi|IPUMS|1987-2008
Malaysia|IPUMS|1991-2000
Maldives|DHS|2009-2016
Mali|IPUMS|1987-2009
Mauritius|IPUMS|1990-2011
Mexico|IPUMS|1970-2015
Moldova|DHS|2005
Mongolia|IPUMS|2000
Morocco|IPUMS|1982-2004
Mozambique|IPUMS|1997-2007
Myanmar|IPUMS|2014
Namibia|DHS|1992-2013
Nepal|IPUMS|2001-2011
Netherlands|LIS|1990-2018
Nicaragua|IPUMS|1995-2005
Niger|DHS|1992-2012
Nigeria|DHS|1990-2018
Norway|Panel Data|1993-2017
Pakistan|LFS|2010-2021
Panama|IPUMS|1960-2010
Papua New Guinea|IPUMS|1980-2000
Paraguay|IPUMS|1962-2002
Peru|IPUMS|1993-2007
Philippines|IPUMS|1990
Poland|LIS|1992-2020
Portugal|IPUMS|1981-2011
Puerto Rico|IPUMS|1990-2010
Romania|IPUMS|1992-2011
Russia|IPUMS|2002-2010
Rwanda|IPUMS|2002-2012
Senegal|IPUMS|1988-2002
Serbia|SILC|2013-2020
Sierra Leone|IPUMS|2004
Slovakia|LIS|1992-2018
Slovenia|LIS|1997-2012
South Africa|IPUMS|1996-2011
South Korea|LIS|2006-2016
South Sudan|IPUMS|2008
Spain|IPUMS|1991-2001
Sudan|IPUMS|2008
Suriname|IPUMS|2012
Sweden|Panel Data|1997-2017
Switzerland|Panel Data|1981-2020
Taiwan|LIS|1981-2016
Tanzania|IPUMS|1988-2012
Thailand|IPUMS|1990-2000
Timor-Leste|DHS|2009-2016
Togo|IPUMS|2010
Trinidad & Tobago|IPUMS|1970-2011
Tunisia|Census|2004
Turkey|IPUMS|1985-2000
Uganda|IPUMS|1991-2014
United Kingdom|APS|2012-2020
United States|CPS/ACS|1968-2020
Uruguay|IPUMS|1963-2011
Venezuela|IPUMS|1971-2001
Vietnam|IPUMS|1989-2009
Zambia|IPUMS|1990-2010
Zimbabwe|IPUMS|2012"

atlas_audit <- read.delim(
  textConnection(atlas_source_text), sep = "|", quote = "",
  stringsAsFactors = FALSE, check.names = FALSE
)
stopifnot(nrow(atlas_audit) == 134)

ipums_pay_yes <- c("Brazil", "Canada", "Jamaica", "Mexico", "Panama", "Puerto Rico", "Venezuela")
ipums_household_only <- "South Africa"

atlas_audit <- atlas_audit |>
  mutate(
    public_access = case_when(
      source == "IPUMS" ~ "Yes: free registration and approved extract",
      source == "DHS" ~ "Yes: free registration and project request",
      source == "MICS" ~ "Yes: free registration/download",
      source == "SILC" ~ "Restricted: Eurostat scientific-use application",
      source == "LIS" ~ "Restricted: LIS membership/remote execution",
      source == "Panel Data" ~ "Restricted; country-specific application",
      source == "LFS" ~ "Varies by national statistical office; verify access",
      source == "APS" ~ "Yes: UK Data Service registration/licence",
      source == "CPS/ACS" ~ "Yes: public-use microdata",
      source == "Mini Census" ~ "Restricted; public microdata not confirmed",
      source == "Census" ~ "Not confirmed from the paper"
    ),
    pay_gap_data = case_when(
      country %in% ipums_pay_yes ~ "Yes/partial: own earnings plus hours/full-time route; verify wave-specific covariates",
      country %in% ipums_household_only ~ "No: household income only; own earnings absent in cited IPUMS censuses",
      source == "IPUMS" ~ "Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination",
      source %in% c("DHS", "MICS") ~ "No: lacks monetary own earnings and hours; industry/occupation detail is also insufficient",
      source == "SILC" ~ "Yes: earnings, hours/full-time, education, occupation, industry, and household structure; access restricted",
      source == "LIS" ~ "Partial/likely: labor earnings and demographics exist; hours and industry/occupation vary by country-wave",
      source == "Panel Data" ~ "Yes for annual-earnings gaps; exact hours/occupation/industry vary and administrative access is restricted",
      source == "LFS" ~ "Unconfirmed: hours, occupation, industry, and education exist, but earnings and public access vary",
      source == "APS" ~ "Yes: earnings, paid hours, education, occupation, industry, and family variables",
      source == "CPS/ACS" ~ "Yes: earnings, hours, education, occupation, industry, and household parent links",
      source == "Mini Census" ~ "Unconfirmed: access and individual earnings documentation not established",
      source == "Census" ~ "Unconfirmed: Atlas documents employment, not a public own-earnings/hourly-wage file"
    )
  )

write.csv(atlas_audit, "results/child_penalty_atlas_data_audit.csv", row.names = FALSE)

atlas_summary <- atlas_audit |>
  mutate(category = case_when(
    grepl("^Yes", pay_gap_data) ~ "Yes",
    grepl("^(Partial|Unconfirmed|Not confirmed)", pay_gap_data) ~ "Partial or unconfirmed",
    TRUE ~ "No"
  )) |>
  count(category, name = "countries")

kable(
  atlas_summary,
  col.names = c("Assessment", "Number of countries"),
  caption = "Summary of the 134-country Atlas audit"
)
Summary of the 134-country Atlas audit
Assessment Number of countries
No 19
Partial or unconfirmed 91
Yes 24
Show R code
kable(
  atlas_audit,
  col.names = c("Country", "Atlas data source", "Atlas years", "Public/research access", "Gender-pay-gap readiness"),
  caption = "Country-level review of the data sources in Kleven et al. (2025), Appendix Table A.1"
)
Country-level review of the data sources in Kleven et al. (2025), Appendix Table A.1
Country Atlas data source Atlas years Public/research access Gender-pay-gap readiness
Afghanistan DHS 2015 Yes: free registration and project request No: lacks monetary own earnings and hours; industry/occupation detail is also insufficient
Albania DHS 2008-2017 Yes: free registration and project request No: lacks monetary own earnings and hours; industry/occupation detail is also insufficient
Algeria MICS 2012-2019 Yes: free registration/download No: lacks monetary own earnings and hours; industry/occupation detail is also insufficient
Angola Census 2014 Not confirmed from the paper Unconfirmed: Atlas documents employment, not a public own-earnings/hourly-wage file
Argentina IPUMS 1970-2001 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Armenia IPUMS 2001-2011 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Australia Panel Data 2001-2019 Restricted; country-specific application Yes for annual-earnings gaps; exact hours/occupation/industry vary and administrative access is restricted
Austria Panel Data 1981-2017 Restricted; country-specific application Yes for annual-earnings gaps; exact hours/occupation/industry vary and administrative access is restricted
Bangladesh IPUMS 1991-2011 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Belarus IPUMS 1999-2009 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Belgium LIS 1985-2017 Restricted: LIS membership/remote execution Partial/likely: labor earnings and demographics exist; hours and industry/occupation vary by country-wave
Benin IPUMS 1979-2013 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Bolivia IPUMS 1976-2001 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Botswana IPUMS 1991-2011 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Brazil IPUMS 1991-2010 Yes: free registration and approved extract Yes/partial: own earnings plus hours/full-time route; verify wave-specific covariates
Bulgaria SILC 2007-2020 Restricted: Eurostat scientific-use application Yes: earnings, hours/full-time, education, occupation, industry, and household structure; access restricted
Burkina Faso IPUMS 1996-2006 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Burundi DHS 2010-2016 Yes: free registration and project request No: lacks monetary own earnings and hours; industry/occupation detail is also insufficient
Cambodia IPUMS 1998-2008 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Cameroon IPUMS 1976-2005 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Canada IPUMS 2011 Yes: free registration and approved extract Yes/partial: own earnings plus hours/full-time route; verify wave-specific covariates
Chad DHS 1996-2014 Yes: free registration and project request No: lacks monetary own earnings and hours; industry/occupation detail is also insufficient
Chile LIS 1990-2017 Restricted: LIS membership/remote execution Partial/likely: labor earnings and demographics exist; hours and industry/occupation vary by country-wave
China Mini Census 2005 Restricted; public microdata not confirmed Unconfirmed: access and individual earnings documentation not established
Colombia IPUMS 1973-2005 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Congo, Dem. Rep. DHS 2007-2013 Yes: free registration and project request No: lacks monetary own earnings and hours; industry/occupation detail is also insufficient
Congo, Rep. DHS 2005-2011 Yes: free registration and project request No: lacks monetary own earnings and hours; industry/occupation detail is also insufficient
Costa Rica IPUMS 1973-2011 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Cote d’Ivoire LIS 2002-2015 Restricted: LIS membership/remote execution Partial/likely: labor earnings and demographics exist; hours and industry/occupation vary by country-wave
Croatia SILC 2010-2020 Restricted: Eurostat scientific-use application Yes: earnings, hours/full-time, education, occupation, industry, and household structure; access restricted
Cuba IPUMS 2002-2012 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Cyprus SILC 2009-2020 Restricted: Eurostat scientific-use application Yes: earnings, hours/full-time, education, occupation, industry, and household structure; access restricted
Czech Republic LIS 1992-2016 Restricted: LIS membership/remote execution Partial/likely: labor earnings and demographics exist; hours and industry/occupation vary by country-wave
Denmark Panel Data 1980-2017 Restricted; country-specific application Yes for annual-earnings gaps; exact hours/occupation/industry vary and administrative access is restricted
Dominican Rep. IPUMS 1981-2010 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Ecuador IPUMS 1982-2010 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Egypt IPUMS 1996-2006 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
El Salvador IPUMS 1992-2007 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Estonia SILC 2009-2020 Restricted: Eurostat scientific-use application Yes: earnings, hours/full-time, education, occupation, industry, and household structure; access restricted
Ethiopia DHS 2000-2016 Yes: free registration and project request No: lacks monetary own earnings and hours; industry/occupation detail is also insufficient
Fiji IPUMS 1976-2014 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Finland SILC 2009-2020 Restricted: Eurostat scientific-use application Yes: earnings, hours/full-time, education, occupation, industry, and household structure; access restricted
France LFS 1990-2020 Varies by national statistical office; verify access Unconfirmed: hours, occupation, industry, and education exist, but earnings and public access vary
Gabon DHS 2000-2012 Yes: free registration and project request No: lacks monetary own earnings and hours; industry/occupation detail is also insufficient
Gambia LFS 2010-2015 Varies by national statistical office; verify access Unconfirmed: hours, occupation, industry, and education exist, but earnings and public access vary
Georgia LFS 2020-2021 Varies by national statistical office; verify access Unconfirmed: hours, occupation, industry, and education exist, but earnings and public access vary
Germany LIS 1989-2005 Restricted: LIS membership/remote execution Partial/likely: labor earnings and demographics exist; hours and industry/occupation vary by country-wave
Ghana IPUMS 2000-2010 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Greece IPUMS 1981-2001 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Guatemala IPUMS 1964-2002 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Guinea IPUMS 1983-2014 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Guyana LFS 2017-2021 Varies by national statistical office; verify access Unconfirmed: hours, occupation, industry, and education exist, but earnings and public access vary
Haiti IPUMS 1971-2003 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Honduras IPUMS 1974-2001 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Hungary IPUMS 1990-2011 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Iceland SILC 2004-2018 Restricted: Eurostat scientific-use application Yes: earnings, hours/full-time, education, occupation, industry, and household structure; access restricted
India DHS 2005-2015 Yes: free registration and project request No: lacks monetary own earnings and hours; industry/occupation detail is also insufficient
Indonesia IPUMS 1971-2010 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Iran IPUMS 2006 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Iraq IPUMS 1997 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Ireland LIS 1994-2018 Restricted: LIS membership/remote execution Partial/likely: labor earnings and demographics exist; hours and industry/occupation vary by country-wave
Israel LIS 1986-2013 Restricted: LIS membership/remote execution Partial/likely: labor earnings and demographics exist; hours and industry/occupation vary by country-wave
Italy LIS 1986-2020 Restricted: LIS membership/remote execution Partial/likely: labor earnings and demographics exist; hours and industry/occupation vary by country-wave
Jamaica IPUMS 1982-2001 Yes: free registration and approved extract Yes/partial: own earnings plus hours/full-time route; verify wave-specific covariates
Japan Panel Data 2004-2020 Restricted; country-specific application Yes for annual-earnings gaps; exact hours/occupation/industry vary and administrative access is restricted
Jordan IPUMS 2004 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Kenya IPUMS 1989-2009 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Kyrgyz Republic DHS 1997-2012 Yes: free registration and project request No: lacks monetary own earnings and hours; industry/occupation detail is also insufficient
Laos IPUMS 2005 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Latvia SILC 2009-2020 Restricted: Eurostat scientific-use application Yes: earnings, hours/full-time, education, occupation, industry, and household structure; access restricted
Lesotho IPUMS 1996-2006 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Liberia IPUMS 2008 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Lithuania LIS 2009-2018 Restricted: LIS membership/remote execution Partial/likely: labor earnings and demographics exist; hours and industry/occupation vary by country-wave
Luxembourg LIS 1985-2013 Restricted: LIS membership/remote execution Partial/likely: labor earnings and demographics exist; hours and industry/occupation vary by country-wave
Madagascar DHS 1992-2008 Yes: free registration and project request No: lacks monetary own earnings and hours; industry/occupation detail is also insufficient
Malawi IPUMS 1987-2008 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Malaysia IPUMS 1991-2000 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Maldives DHS 2009-2016 Yes: free registration and project request No: lacks monetary own earnings and hours; industry/occupation detail is also insufficient
Mali IPUMS 1987-2009 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Mauritius IPUMS 1990-2011 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Mexico IPUMS 1970-2015 Yes: free registration and approved extract Yes/partial: own earnings plus hours/full-time route; verify wave-specific covariates
Moldova DHS 2005 Yes: free registration and project request No: lacks monetary own earnings and hours; industry/occupation detail is also insufficient
Mongolia IPUMS 2000 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Morocco IPUMS 1982-2004 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Mozambique IPUMS 1997-2007 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Myanmar IPUMS 2014 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Namibia DHS 1992-2013 Yes: free registration and project request No: lacks monetary own earnings and hours; industry/occupation detail is also insufficient
Nepal IPUMS 2001-2011 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Netherlands LIS 1990-2018 Restricted: LIS membership/remote execution Partial/likely: labor earnings and demographics exist; hours and industry/occupation vary by country-wave
Nicaragua IPUMS 1995-2005 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Niger DHS 1992-2012 Yes: free registration and project request No: lacks monetary own earnings and hours; industry/occupation detail is also insufficient
Nigeria DHS 1990-2018 Yes: free registration and project request No: lacks monetary own earnings and hours; industry/occupation detail is also insufficient
Norway Panel Data 1993-2017 Restricted; country-specific application Yes for annual-earnings gaps; exact hours/occupation/industry vary and administrative access is restricted
Pakistan LFS 2010-2021 Varies by national statistical office; verify access Unconfirmed: hours, occupation, industry, and education exist, but earnings and public access vary
Panama IPUMS 1960-2010 Yes: free registration and approved extract Yes/partial: own earnings plus hours/full-time route; verify wave-specific covariates
Papua New Guinea IPUMS 1980-2000 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Paraguay IPUMS 1962-2002 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Peru IPUMS 1993-2007 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Philippines IPUMS 1990 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Poland LIS 1992-2020 Restricted: LIS membership/remote execution Partial/likely: labor earnings and demographics exist; hours and industry/occupation vary by country-wave
Portugal IPUMS 1981-2011 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Puerto Rico IPUMS 1990-2010 Yes: free registration and approved extract Yes/partial: own earnings plus hours/full-time route; verify wave-specific covariates
Romania IPUMS 1992-2011 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Russia IPUMS 2002-2010 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Rwanda IPUMS 2002-2012 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Senegal IPUMS 1988-2002 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Serbia SILC 2013-2020 Restricted: Eurostat scientific-use application Yes: earnings, hours/full-time, education, occupation, industry, and household structure; access restricted
Sierra Leone IPUMS 2004 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Slovakia LIS 1992-2018 Restricted: LIS membership/remote execution Partial/likely: labor earnings and demographics exist; hours and industry/occupation vary by country-wave
Slovenia LIS 1997-2012 Restricted: LIS membership/remote execution Partial/likely: labor earnings and demographics exist; hours and industry/occupation vary by country-wave
South Africa IPUMS 1996-2011 Yes: free registration and approved extract No: household income only; own earnings absent in cited IPUMS censuses
South Korea LIS 2006-2016 Restricted: LIS membership/remote execution Partial/likely: labor earnings and demographics exist; hours and industry/occupation vary by country-wave
South Sudan IPUMS 2008 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Spain IPUMS 1991-2001 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Sudan IPUMS 2008 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Suriname IPUMS 2012 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Sweden Panel Data 1997-2017 Restricted; country-specific application Yes for annual-earnings gaps; exact hours/occupation/industry vary and administrative access is restricted
Switzerland Panel Data 1981-2020 Restricted; country-specific application Yes for annual-earnings gaps; exact hours/occupation/industry vary and administrative access is restricted
Taiwan LIS 1981-2016 Restricted: LIS membership/remote execution Partial/likely: labor earnings and demographics exist; hours and industry/occupation vary by country-wave
Tanzania IPUMS 1988-2012 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Thailand IPUMS 1990-2000 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Timor-Leste DHS 2009-2016 Yes: free registration and project request No: lacks monetary own earnings and hours; industry/occupation detail is also insufficient
Togo IPUMS 2010 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Trinidad & Tobago IPUMS 1970-2011 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Tunisia Census 2004 Not confirmed from the paper Unconfirmed: Atlas documents employment, not a public own-earnings/hourly-wage file
Turkey IPUMS 1985-2000 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Uganda IPUMS 1991-2014 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
United Kingdom APS 2012-2020 Yes: UK Data Service registration/licence Yes: earnings, paid hours, education, occupation, industry, and family variables
United States CPS/ACS 1968-2020 Yes: public-use microdata Yes: earnings, hours, education, occupation, industry, and household parent links
Uruguay IPUMS 1963-2011 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Venezuela IPUMS 1971-2001 Yes: free registration and approved extract Yes/partial: own earnings plus hours/full-time route; verify wave-specific covariates
Vietnam IPUMS 1989-2009 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Zambia IPUMS 1990-2010 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination
Zimbabwe IPUMS 2012 Yes: free registration and approved extract Not confirmed: Atlas employment file lacks a verified own-earnings + hours/full-time combination

The Atlas table is a source audit, not a guarantee of variable access. In particular, “Panel Data” often means confidential administrative registers; LIS provides harmonized output through a remote system rather than distributing national microdata; EU-SILC scientific-use files require approval; and national labor-force-survey earnings modules vary. The machine-readable audit is available in results/child_penalty_atlas_data_audit.csv.

Access documentation: IPUMS International, DHS Program, UNICEF MICS, Luxembourg Income Study, Eurostat microdata access, UK Annual Population Survey, and U.S. CPS.

Five comparability cautions apply even to feasible settings. First, co-resident parenthood misses nonresident and older children, while fertility-history parenthood is generally women-only. Second, INCWAGE and INCEARN are different concepts; the latter includes business and farm earnings. Third, income can be reported weekly, monthly, or annually and is subject to sample-specific universes and top-codes; numerator and hours must be placed on a common period within each sample. Fourth, HRSFULL definitions vary across countries and waves. Fifth, broad industry and occupation harmonization can still contain source-classification breaks. A real analysis should read every sample-specific comparability tab and apply IPUMS person weights.

Sources: sample catalogue and country sample-detail pages; variable documentation for INCWAGE, INCEARN, HRSWORK1, HRSUSUAL1, HRSMAIN, HRSACTUAL1, HRSFULL, NCHILD, MOMLOC, POPLOC, CHBORN, CHSURV, LASTBYR, INDGEN, and OCCISCO.

Conclusions

  • The synthetic mean log-wage gap narrows over the three censuses.
  • Parenthood remains associated with larger gaps, while selection into employment makes the marriage gradient vary across waves.
  • Women’s educational gains remove education as an explanation and can make its contribution negative.
  • Occupational and industrial sorting remain meaningful explained components even as segregation declines.
  • Both changing characteristics and a declining unexplained component contribute to convergence from 1995.
  • Distributional decompositions reveal that a single mean gap can conceal different composition and coefficient effects across the wage distribution.

Reproduction and files

The report source is krabbistan-gender-gap.qmd. Running

quarto render krabbistan-gender-gap.qmd

regenerates the census files, all CSV result tables, figures, and this self-contained HTML. The optional code/krabbistan_gender_gap.do contains a standalone Stata translation of the simulation and mean/distributional decomposition workflow.

Downloads:

Reference

Blau, Francine D., and Lawrence M. Kahn. 2017. “The Gender Wage Gap: Extent, Trends, and Explanations.” Journal of Economic Literature 55 (3): 789–865. https://doi.org/10.1257/jel.20160995

Kleven, Henrik, Camille Landais, and Gabriel Leite-Mariante. 2025. “The Child Penalty Atlas.” Review of Economic Studies 92 (5): 3174–3207. https://doi.org/10.1093/restud/rdae104. Country sources are transcribed from Appendix Table A.1.