# ── Install missing packages automatically ──────────────────────────────────
pkgs <- c("tidyverse", "scales", "ggtext", "patchwork",
"knitr", "kableExtra", "gt", "RColorBrewer")
installed <- rownames(installed.packages())
for (p in pkgs) {
if (!p %in% installed) install.packages(p, repos = "https://cloud.r-project.org")
}
library(tidyverse)
library(scales)
library(ggtext)
library(patchwork)
library(knitr)
library(kableExtra)
library(gt)
# ── Brand colors ────────────────────────────────────────────────────────────
CLR_INK <- "#0f0e0c"
CLR_CREAM <- "#f5f0e8"
CLR_RUST <- "#c0392b"
CLR_SAND <- "#e8dcc8"
CLR_SAGE <- "#4a6741"
CLR_AMBER <- "#d4851a"
CLR_SLATE <- "#3d4a5c"
CLR_PALE <- "#faf7f2"
CLR_LGREY <- "#eeebe5"
# ── Custom ggplot2 theme ────────────────────────────────────────────────────
theme_unequal <- function(base_size = 11) {
theme_minimal(base_size = base_size) +
theme(
plot.background = element_rect(fill = CLR_PALE, color = NA),
panel.background = element_rect(fill = "white", color = NA),
panel.grid.major = element_line(color = CLR_LGREY, linewidth = 0.4),
panel.grid.minor = element_blank(),
axis.ticks = element_blank(),
axis.text = element_text(color = "#555555", size = 9),
axis.title = element_text(color = "#555555", size = 9, face = "plain"),
plot.title = element_text(color = CLR_INK, size = 14, face = "bold",
margin = margin(b = 4)),
plot.subtitle = element_text(color = "#555555", size = 9,
margin = margin(b = 12)),
plot.caption = element_text(color = "#999999", size = 7.5,
hjust = 0, margin = margin(t = 10)),
legend.position = "top",
legend.key.size = unit(0.45, "cm"),
legend.text = element_text(size = 8.5, color = "#444"),
legend.title = element_blank(),
strip.text = element_text(face = "bold", color = CLR_INK),
plot.margin = margin(16, 16, 16, 16)
)
}
theme_set(theme_unequal())
Introduction
“Nearly all countries (93%) take some approach to prohibiting
gender discrimination at work — yet women from marginalized groups often
lack full legal protections.” — WORLD Policy Analysis Center
(2023)
This report examines how race, gender, disability, religion,
social class, migration status, sexual orientation, and
age intersect to produce compounding workplace
disadvantages. Drawing on data from the U.S. Bureau of Labor Statistics,
the U.S. Census Bureau, and the WORLD Policy Analysis Center’s
Discrimination at Work Database, we present six visualizations and a set
of evidence-based policy recommendations.
Key Findings
At a Glance
findings <- tibble::tribble(
~Statistic, ~Finding,
"93%", "of countries prohibit gender-based employment discrimination — yet women from marginalized groups frequently lack full legal protection in practice.",
"17%", "of countries protect workers from discrimination based on gender identity, leaving the vast majority of transgender workers without recourse.",
"82¢", "Women in the U.S. earn for every $1 earned by men — a gap that widens sharply when race is factored in.",
"56¢", "'Racialized' women in Canada earn for each dollar earned by White men — a stark illustration of intersecting disadvantage.",
"2×", "Migrant women's income disadvantage in China exceeds the combined individual penalties of being female and being an unregistered migrant.",
"35%", "of countries ban employment discrimination based on sexual orientation — leaving the majority of LGBTQ+ workers unprotected."
)
findings |>
gt() |>
tab_header(
title = md("**Key Findings at a Glance**"),
subtitle = "Unequal Ground: Workplace Discrimination & The Gender Pay Gap"
) |>
cols_label(Statistic = "Statistic", Finding = "Finding") |>
tab_style(
style = list(
cell_fill(color = CLR_RUST),
cell_text(color = "white", weight = "bold", size = px(16))
),
locations = cells_body(columns = Statistic)
) |>
tab_style(
style = cell_text(size = px(13)),
locations = cells_body(columns = Finding)
) |>
tab_style(
style = list(
cell_fill(color = CLR_INK),
cell_text(color = CLR_CREAM, weight = "bold")
),
locations = cells_column_labels()
) |>
tab_options(
table.width = pct(100),
table.border.top.color = CLR_RUST,
table.border.top.width = px(3),
row.striping.background = CLR_PALE,
row.striping.include_table_body = TRUE
)
| Key Findings at a Glance |
| Unequal Ground: Workplace Discrimination & The Gender Pay Gap |
| Statistic |
Finding |
| 93% |
of countries prohibit gender-based employment discrimination — yet women from marginalized groups frequently lack full legal protection in practice. |
| 17% |
of countries protect workers from discrimination based on gender identity, leaving the vast majority of transgender workers without recourse. |
| 82¢ |
Women in the U.S. earn for every $1 earned by men — a gap that widens sharply when race is factored in. |
| 56¢ |
'Racialized' women in Canada earn for each dollar earned by White men — a stark illustration of intersecting disadvantage. |
| 2× |
Migrant women's income disadvantage in China exceeds the combined individual penalties of being female and being an unregistered migrant. |
| 35% |
of countries ban employment discrimination based on sexual orientation — leaving the majority of LGBTQ+ workers unprotected. |
Visualization 1 — Gender Wage Gap by Race & Ethnicity
Data
# ── U.S. BLS Usual Weekly Earnings, Q4 2023 ─────────────────────────────────
# Expressed as cents per dollar earned by White men (baseline = 100)
wage_gap <- tibble(
group = c(
"White Men", "Asian Men", "White Women", "Black Men",
"Hispanic Men", "Asian Women", "Black Women", "Hispanic Women"
),
earnings_pct = c(100, 115, 82, 73, 68, 93, 67, 58),
gender = c("Men", "Men", "Women", "Men", "Men", "Women", "Women", "Women"),
race = c("White", "Asian", "White", "Black",
"Hispanic", "Asian", "Black", "Hispanic")
) |>
mutate(
group = fct_reorder(group, earnings_pct),
bar_color = case_when(
gender == "Women" ~ CLR_RUST,
group == "White Men" ~ CLR_INK,
TRUE ~ CLR_SLATE
)
)
wage_gap |>
select(group, gender, race, earnings_pct) |>
arrange(desc(earnings_pct)) |>
kable(
col.names = c("Group", "Gender", "Race/Ethnicity", "Earnings (¢ per $1)"),
caption = "Median Weekly Earnings as % of White Men's Earnings (U.S., Q4 2023)"
) |>
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE) |>
row_spec(0, background = CLR_INK, color = CLR_CREAM, bold = TRUE)
Median Weekly Earnings as % of White Men’s Earnings (U.S., Q4 2023)
|
Group
|
Gender
|
Race/Ethnicity
|
Earnings (¢ per $1)
|
|
Asian Men
|
Men
|
Asian
|
115
|
|
White Men
|
Men
|
White
|
100
|
|
Asian Women
|
Women
|
Asian
|
93
|
|
White Women
|
Women
|
White
|
82
|
|
Black Men
|
Men
|
Black
|
73
|
|
Hispanic Men
|
Men
|
Hispanic
|
68
|
|
Black Women
|
Women
|
Black
|
67
|
|
Hispanic Women
|
Women
|
Hispanic
|
58
|
Chart
p1 <- ggplot(wage_gap, aes(x = group, y = earnings_pct, fill = bar_color)) +
geom_col(width = 0.72, show.legend = FALSE) +
geom_hline(yintercept = 100, color = CLR_RUST,
linetype = "dashed", linewidth = 0.8) +
geom_text(aes(label = paste0(earnings_pct, "¢"),
vjust = ifelse(earnings_pct < 20, -0.4, 1.4)),
color = "white", fontface = "bold", size = 3.3) +
annotate("text", x = 8.4, y = 101.5, label = "White men baseline ($1.00)",
color = CLR_RUST, size = 2.8, hjust = 1, fontface = "italic") +
scale_fill_identity() +
scale_y_continuous(
limits = c(0, 125),
labels = function(x) paste0(x, "¢"),
expand = c(0, 0)
) +
coord_flip() +
labs(
title = "Median Earnings as % of White Men's Earnings (U.S., 2023)",
subtitle = "Red bars = women; dark bars = men. Dashed line = White men baseline ($1.00).",
x = NULL,
y = "Cents per dollar earned by White men",
caption = "Source: U.S. Bureau of Labor Statistics, Usual Weekly Earnings, Q4 2023"
)
p1

Visualization 2 — Historical Wage Gap Trend (1980–2023)
Data
# ── U.S. Census Bureau, Current Population Survey ───────────────────────────
wage_trend <- tibble(
year = c(1980, 1985, 1990, 1995, 2000, 2005,
2010, 2015, 2018, 2020, 2022, 2023),
earnings = c(60, 64, 71, 71, 73, 76,
77, 80, 81, 82, 82, 82)
)
wage_trend |>
kable(
col.names = c("Year", "Women's Earnings (¢ per $1 earned by men)"),
caption = "Gender Pay Ratio Trend, U.S. Full-Time Workers, 1980–2023"
) |>
kable_styling(bootstrap_options = c("striped", "hover"),
full_width = FALSE) |>
row_spec(0, background = CLR_INK, color = CLR_CREAM, bold = TRUE)
Gender Pay Ratio Trend, U.S. Full-Time Workers, 1980–2023
|
Year
|
Women’s Earnings (¢ per $1 earned by men)
|
|
1980
|
60
|
|
1985
|
64
|
|
1990
|
71
|
|
1995
|
71
|
|
2000
|
73
|
|
2005
|
76
|
|
2010
|
77
|
|
2015
|
80
|
|
2018
|
81
|
|
2020
|
82
|
|
2022
|
82
|
|
2023
|
82
|
Chart
# Annotate key policy milestones
milestones <- tibble(
year = c(1963, 1978, 1993, 2009),
label = c("Equal Pay Act", "Pregnancy\nDiscrimination Act",
"Family &\nMedical Leave", "Lilly Ledbetter\nFair Pay Act"),
y = c(62, 66, 74, 80)
)
p2 <- ggplot(wage_trend, aes(x = year, y = earnings)) +
geom_ribbon(aes(ymin = 55, ymax = earnings),
fill = CLR_RUST, alpha = 0.12) +
geom_line(color = CLR_RUST, linewidth = 1.8) +
geom_point(color = CLR_RUST, size = 3, shape = 21,
fill = "white", stroke = 2) +
geom_text(aes(label = paste0(earnings, "¢")),
vjust = -0.9, size = 2.8, color = CLR_RUST, fontface = "bold") +
scale_x_continuous(breaks = seq(1980, 2023, 5)) +
scale_y_continuous(
limits = c(55, 100),
labels = function(x) paste0(x, "¢"),
breaks = seq(60, 100, 10)
) +
labs(
title = "Women's Earnings Relative to Men's — U.S., 1980–2023",
subtitle = "Despite 40+ years of progress, the gap stalled at ~82¢ after 2018.",
x = "Year",
y = "Cents per dollar earned by men",
caption = "Source: U.S. Census Bureau, Current Population Survey"
)
p2

Visualization 3 — Global Legal Protections by Category
Data
protections <- tibble(
category = c(
"Gender & Religion", "Gender & Race/Ethnicity", "Gender & Disability",
"Gender & Age", "Gender & Social Class", "Gender & Foreign Origin",
"Gender & Migration Status", "Sexual Orientation", "Gender Identity"
),
pct_2016 = c(80, 80, 74, 65, 60, 42, 40, 28, 12),
pct_2021 = c(83, 82, 80, 65, 64, 48, 47, 35, 17)
) |>
mutate(
change = pct_2021 - pct_2016,
category = fct_reorder(category, pct_2021)
)
protections |>
arrange(desc(pct_2021)) |>
mutate(change = paste0(ifelse(change > 0, "+", ""), change, " pp")) |>
kable(
col.names = c("Category", "2016 (%)", "2021 (%)", "Change"),
caption = "Country-Level Employment Discrimination Protections (% of 193 countries)"
) |>
kable_styling(bootstrap_options = c("striped", "hover"),
full_width = FALSE) |>
row_spec(0, background = CLR_INK, color = CLR_CREAM, bold = TRUE) |>
column_spec(4, bold = TRUE, color = CLR_SAGE)
Country-Level Employment Discrimination Protections (% of 193 countries)
|
Category
|
2016 (%)
|
2021 (%)
|
Change
|
|
Gender & Religion
|
80
|
83
|
+3 pp
|
|
Gender & Race/Ethnicity
|
80
|
82
|
+2 pp
|
|
Gender & Disability
|
74
|
80
|
+6 pp
|
|
Gender & Age
|
65
|
65
|
0 pp
|
|
Gender & Social Class
|
60
|
64
|
+4 pp
|
|
Gender & Foreign Origin
|
42
|
48
|
+6 pp
|
|
Gender & Migration Status
|
40
|
47
|
+7 pp
|
|
Sexual Orientation
|
28
|
35
|
+7 pp
|
|
Gender Identity
|
12
|
17
|
+5 pp
|
Chart
prot_long <- protections |>
pivot_longer(cols = c(pct_2016, pct_2021),
names_to = "year",
values_to = "pct") |>
mutate(year = recode(year, pct_2016 = "2016", pct_2021 = "2021"))
p3 <- ggplot(prot_long,
aes(x = pct, y = category, fill = year)) +
geom_col(position = position_dodge(width = 0.7),
width = 0.6, show.legend = TRUE) +
geom_text(aes(label = paste0(pct, "%")),
position = position_dodge(width = 0.7),
hjust = -0.15, size = 2.8, color = CLR_INK) +
scale_fill_manual(values = c("2016" = CLR_SLATE, "2021" = CLR_RUST)) +
scale_x_continuous(
limits = c(0, 105),
labels = function(x) paste0(x, "%"),
expand = c(0, 0)
) +
labs(
title = "% of Countries Prohibiting Workplace Discrimination by Category",
subtitle = "2016 vs. 2021 — progress is real but gaps in LGBTQ+ protections remain severe.",
x = "% of 193 countries",
y = NULL,
caption = "Source: WORLD Policy Analysis Center, Discrimination at Work Database"
)
p3

Visualization 4 — Disability & Age Penalties
Data
# Involuntary job loss risk — U.S., workers with disabilities vs. without
disability_risk <- tibble(
group = c("Men with\ndisabilities", "Women with\ndisabilities"),
pct_higher = c(75, 89),
gender = c("Men", "Women")
)
# Employer-funded training among 50+ workers — 9-country EU study
training <- tibble(
category = c("Men (employer-funded)", "Women (employer-funded)",
"Women (self-funded)"),
proportion = c(58, 32, 10),
fill_color = c(CLR_SLATE, CLR_RUST, CLR_AMBER)
)
Charts
p4a <- ggplot(disability_risk,
aes(x = group, y = pct_higher, fill = gender)) +
geom_col(width = 0.5, show.legend = FALSE) +
geom_text(aes(label = paste0("+", pct_higher, "%")),
vjust = -0.5, fontface = "bold", size = 4.5, color = CLR_INK) +
scale_fill_manual(values = c("Men" = CLR_SLATE, "Women" = CLR_RUST)) +
scale_y_continuous(
limits = c(0, 105),
labels = function(x) paste0("+", x, "%"),
expand = c(0, 0)
) +
labs(
title = "Involuntary Job Loss Risk\n(Workers with Disabilities, U.S.)",
subtitle = "% MORE likely vs. workers without disabilities",
x = NULL,
y = "Increased risk",
caption = "Source: WORLD Policy Analysis Center (2023)"
)
p4b <- ggplot(training,
aes(x = "", y = proportion, fill = fill_color)) +
geom_col(width = 0.6, color = "white", linewidth = 0.8) +
geom_text(aes(label = paste0(category, "\n", proportion, "%")),
position = position_stack(vjust = 0.5),
size = 2.8, color = "white", fontface = "bold") +
scale_fill_identity() +
coord_polar(theta = "y") +
labs(
title = "Employer-Funded Training\n(Workers Age 50+, 9-Country EU Study)",
subtitle = "Men significantly more likely to receive employer-funded training",
caption = "Source: WORLD Policy Analysis Center (2023)"
) +
theme_void() +
theme(
plot.title = element_text(face = "bold", size = 12, hjust = 0.5,
color = CLR_INK),
plot.subtitle = element_text(size = 8.5, hjust = 0.5, color = "#555"),
plot.caption = element_text(size = 7.5, hjust = 0.5, color = "#999",
margin = margin(t = 8)),
plot.background = element_rect(fill = CLR_PALE, color = NA)
)
p4a + p4b +
plot_annotation(
title = "Visualization 4 — Disability and Age: Compounding Penalties",
caption = "Workers with disabilities and older workers — particularly women — face layered disadvantages.",
theme = theme(
plot.title = element_text(face = "bold", size = 14, color = CLR_INK),
plot.caption = element_text(size = 8.5, color = "#666",
margin = margin(t = 6))
)
)

Visualization 5 — Intersectional Discrimination Table
matrix_df <- tibble::tribble(
~`Identity Intersection`, ~`Key Evidence`, ~`Countries Protected`,
"Race + Gender", "Arab/N.African women in Belgium less likely selected for cognitive-role interviews than men of same background.", "82%",
"Religion + Gender", "Muslim women in Britain are the most economically disadvantaged group (2011 census analysis).", "83%",
"Disability + Gender", "Women of color with disabilities face highest workplace harassment rates (multiple studies).", "80%",
"SOGIESC + Gender", "60% of trans women in EU reported job-search discrimination in 2012 (EU FRA survey).", "35%",
"Migration + Gender", "In China, migrant women's disadvantage exceeds the combined individual penalties of gender + migration status.", "47%",
"Social Class + Gender", "In U.S., 'higher-class' men got callbacks 16% of the time vs. 4% for 'higher-class' women.", "64%",
"Age + Gender", "In Germany, unexplained gender wage gap grows after age 45, suggesting compounding discrimination.", "65%",
"Caste + Gender", "In India, women from disadvantaged castes experience greater wage inequality than other women.", "Varies"
)
matrix_df |>
gt() |>
tab_header(
title = md("**Visualization 5 — Intersectional Discrimination Matrix**"),
subtitle = "Where multiple marginalized identities converge to compound disadvantage"
) |>
cols_label(
`Identity Intersection` = "Identity Intersection",
`Key Evidence` = "Key Evidence",
`Countries Protected` = "% Countries w/ Protection"
) |>
tab_style(
style = list(
cell_fill(color = CLR_RUST),
cell_text(color = "white", weight = "bold")
),
locations = cells_body(columns = `Identity Intersection`)
) |>
tab_style(
style = list(
cell_fill(color = CLR_INK),
cell_text(color = CLR_CREAM, weight = "bold")
),
locations = cells_column_labels()
) |>
tab_style(
style = cell_text(weight = "bold", color = CLR_RUST),
locations = cells_body(columns = `Countries Protected`)
) |>
tab_style(
style = cell_fill(color = CLR_PALE),
locations = cells_body(rows = seq(1, nrow(matrix_df), 2))
) |>
tab_options(
table.width = pct(100),
table.border.top.color = CLR_RUST,
table.border.top.width = px(3)
)
| Visualization 5 — Intersectional Discrimination Matrix |
| Where multiple marginalized identities converge to compound disadvantage |
| Identity Intersection |
Key Evidence |
% Countries w/ Protection |
| Race + Gender |
Arab/N.African women in Belgium less likely selected for cognitive-role interviews than men of same background. |
82% |
| Religion + Gender |
Muslim women in Britain are the most economically disadvantaged group (2011 census analysis). |
83% |
| Disability + Gender |
Women of color with disabilities face highest workplace harassment rates (multiple studies). |
80% |
| SOGIESC + Gender |
60% of trans women in EU reported job-search discrimination in 2012 (EU FRA survey). |
35% |
| Migration + Gender |
In China, migrant women's disadvantage exceeds the combined individual penalties of gender + migration status. |
47% |
| Social Class + Gender |
In U.S., 'higher-class' men got callbacks 16% of the time vs. 4% for 'higher-class' women. |
64% |
| Age + Gender |
In Germany, unexplained gender wage gap grows after age 45, suggesting compounding discrimination. |
65% |
| Caste + Gender |
In India, women from disadvantaged castes experience greater wage inequality than other women. |
Varies |
Visualization 6 — Protections by Country Income Group
Data
income_df <- tibble::tribble(
~category, ~high, ~middle, ~low, ~status,
"Gender & Disability", 86, 75, 67, "Partial gap",
"Gender & Religion", 79, 85, 85, "Broad coverage",
"Gender & Race/Ethnicity", 82, 80, 78, "Partial gap",
"Gender & Social Class", 40, 77, 60, "Significant gap",
"Gender & Migration Status", 45, 50, 56, "Significant gap",
"Sexual Orientation", 62, 22, 7, "Critical gap",
"Gender Identity", 36, 10, 4, "Critical gap"
)
Chart
income_long <- income_df |>
pivot_longer(cols = c(high, middle, low),
names_to = "income_group",
values_to = "pct") |>
mutate(
income_group = factor(income_group,
levels = c("high", "middle", "low"),
labels = c("High Income", "Middle Income", "Low Income")),
category = fct_reorder(category, pct, .fun = max)
)
p6 <- ggplot(income_long,
aes(x = pct, y = category, fill = income_group)) +
geom_col(position = position_dodge(width = 0.75), width = 0.65) +
geom_text(aes(label = paste0(pct, "%")),
position = position_dodge(width = 0.75),
hjust = -0.15, size = 2.6, color = CLR_INK) +
scale_fill_manual(
values = c("High Income" = CLR_SLATE,
"Middle Income" = CLR_AMBER,
"Low Income" = CLR_RUST)
) +
scale_x_continuous(
limits = c(0, 105),
labels = function(x) paste0(x, "%"),
expand = c(0, 0)
) +
labs(
title = "Legal Protections by Country Income Group (2021)",
subtitle = "High-income countries lead on LGBTQ+ protections; low-income lead on religion and migration.",
x = "% of countries with protections",
y = NULL,
fill = "Income Group",
caption = "Source: WORLD Policy Analysis Center, Discrimination at Work Database (2021)"
)
p6

Table
income_df |>
select(-status) |>
rename(
"Protection Category" = category,
"High Income (%)" = high,
"Middle Income (%)" = middle,
"Low Income (%)" = low
) |>
gt() |>
tab_header(
title = md("**Protections by Country Income Group**"),
subtitle = "% of countries with employment discrimination protections (2021)"
) |>
tab_style(
style = list(
cell_fill(color = CLR_INK),
cell_text(color = CLR_CREAM, weight = "bold")
),
locations = cells_column_labels()
) |>
data_color(
columns = c(`High Income (%)`, `Middle Income (%)`, `Low Income (%)`),
palette = c(CLR_CREAM, CLR_RUST),
domain = c(0, 100)
) |>
tab_options(
table.width = pct(100),
table.border.top.color = CLR_RUST,
table.border.top.width = px(3)
)
| Protections by Country Income Group |
| % of countries with employment discrimination protections (2021) |
| Protection Category |
High Income (%) |
Middle Income (%) |
Low Income (%) |
| Gender & Disability |
86 |
75 |
67 |
| Gender & Religion |
79 |
85 |
85 |
| Gender & Race/Ethnicity |
82 |
80 |
78 |
| Gender & Social Class |
40 |
77 |
60 |
| Gender & Migration Status |
45 |
50 |
56 |
| Sexual Orientation |
62 |
22 |
7 |
| Gender Identity |
36 |
10 |
4 |
Policy Recommendations
recs <- tibble::tribble(
~`#`, ~Recommendation, ~Evidence_Base,
"1", "Mandate intersectional protections.",
"Anti-discrimination law must explicitly cover combinations of identities — not just each category independently.",
"2", "Expand SOGIESC coverage.",
"Only 35% of countries ban sexual orientation discrimination; 17% address gender identity.",
"3", "Guarantee reasonable accommodations.",
"80% address gender-disability discrimination, but only 59% require accommodations.",
"4", "Protect migrant workers.",
"Fewer than 47% of countries address gender discrimination for migrant workers.",
"5", "Require pay transparency.",
"Salary disclosure enables detection of unexplained wage gaps at age and seniority intersections.",
"6", "Collect intersectional workforce data.",
"Disaggregate data by race × gender, disability × gender, etc. to reveal compounding penalties.",
"7", "Address structural exclusions.",
"Domestic and informal workers — disproportionately women of color — are often excluded from labor law.",
"8", "Fund enforcement mechanisms.",
"Laws without enforcement are symbolic. Dedicated agencies with investigation authority are essential."
)
recs |>
gt() |>
tab_header(
title = md("**Policy Recommendations**"),
subtitle = "What the Data Demands — Eight Evidence-Based Actions"
) |>
cols_label(`#` = "#", Recommendation = "Recommendation",
Evidence_Base = "Evidence Base") |>
tab_style(
style = list(
cell_fill(color = CLR_RUST),
cell_text(color = "white", weight = "bold", align = "center", size = px(15))
),
locations = cells_body(columns = `#`)
) |>
tab_style(
style = cell_text(weight = "bold"),
locations = cells_body(columns = Recommendation)
) |>
tab_style(
style = list(
cell_fill(color = CLR_INK),
cell_text(color = CLR_CREAM, weight = "bold")
),
locations = cells_column_labels()
) |>
tab_style(
style = cell_fill(color = CLR_PALE),
locations = cells_body(rows = seq(1, nrow(recs), 2))
) |>
tab_options(
table.width = pct(100),
table.border.top.color = CLR_RUST,
table.border.top.width = px(3)
)
| Policy Recommendations |
| What the Data Demands — Eight Evidence-Based Actions |
| # |
Recommendation |
Evidence Base |
| 1 |
Mandate intersectional protections. |
Anti-discrimination law must explicitly cover combinations of identities — not just each category independently. |
| 2 |
Expand SOGIESC coverage. |
Only 35% of countries ban sexual orientation discrimination; 17% address gender identity. |
| 3 |
Guarantee reasonable accommodations. |
80% address gender-disability discrimination, but only 59% require accommodations. |
| 4 |
Protect migrant workers. |
Fewer than 47% of countries address gender discrimination for migrant workers. |
| 5 |
Require pay transparency. |
Salary disclosure enables detection of unexplained wage gaps at age and seniority intersections. |
| 6 |
Collect intersectional workforce data. |
Disaggregate data by race × gender, disability × gender, etc. to reveal compounding penalties. |
| 7 |
Address structural exclusions. |
Domestic and informal workers — disproportionately women of color — are often excluded from labor law. |
| 8 |
Fund enforcement mechanisms. |
Laws without enforcement are symbolic. Dedicated agencies with investigation authority are essential. |
Data Sources
sources <- tibble::tribble(
~Source, ~Description, ~URL,
"U.S. Bureau of Labor Statistics (BLS)",
"Usual Weekly Earnings of Wage and Salary Workers, Q4 2023",
"https://www.bls.gov/news.release/wkyeng.toc.htm",
"U.S. Census Bureau",
"Current Population Survey, Historical Income Tables, 1980–2023",
"https://www.census.gov/topics/income-poverty/income/data/tables.html",
"WORLD Policy Analysis Center",
"Discrimination at Work Database, 2016 & 2021",
"https://worldpolicycenter.org",
"Heymann, Sprague & Raub (2023)",
"Equality within Our Lifetimes — UC Press (Chapter 3)",
"https://www.ucpress.edu/book/9780520387126",
"OECD",
"Employment Outlook 2023",
"https://www.oecd.org/employment/outlook",
"EU Fundamental Rights Agency",
"LGBTQ Survey 2012 & Being LGBTIQ in the EU (2019)",
"https://fra.europa.eu",
"TidyTuesday / Kaggle / data.world",
"Open data repositories used for supplemental exploration",
"https://github.com/rfordatascience/tidytuesday"
)
sources |>
kable(
col.names = c("Source", "Description", "URL"),
caption = "Data Sources"
) |>
kable_styling(bootstrap_options = c("striped", "hover"),
full_width = TRUE) |>
row_spec(0, background = CLR_INK, color = CLR_CREAM, bold = TRUE) |>
column_spec(3, link = sources$URL, color = CLR_RUST)
SOPE 512 — Laboratory Coding, Software, & Data Collection
Methods | Spring 2026 Analysis modeled after: WORLD Policy
Analysis Center, “Addressing Multiple Sources of Discrimination at Work”
(Feb. 2023)