Data and methods

We use the World Bank World Development Indicators series SL.AGR.EMPL.FE.ZS (Employment in agriculture, female (% of female employment), modeled ILO estimate) for 1960–2024, and World Bank country metadata for regional and income‑group classifications.[file:4][file:5][file:3]

main <- readr::read_csv(
"API_SL.AGR.EMPL.FE.ZS_DS2_en_csv_v2_1797.csv",
skip = 4
)
## New names:
## Rows: 266 Columns: 70
## ── Column specification
## ──────────────────────────────────────────────────────── Delimiter: "," chr
## (4): Country Name, Country Code, Indicator Name, Indicator Code dbl (33): 1991,
## 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, ... lgl (33): 1960,
## 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, ...
## ℹ Use `spec()` to retrieve the full column specification for this data. ℹ
## Specify the column types or set `show_col_types = FALSE` to quiet this message.
## • `` -> `...70`

Country metadata (Region, IncomeGroup)

meta_cty <- readr::read_csv(“Metadata_Country_API_SL.AGR.EMPL.FE.ZS_DS2_en_csv_v2_1797.csv”)

meta_cty <- readr::read_csv("Metadata_Country_API_SL.AGR.EMPL.FE.ZS_DS2_en_csv_v2_1797.csv")
## New names:
## Rows: 265 Columns: 6
## ── Column specification
## ──────────────────────────────────────────────────────── Delimiter: "," chr
## (5): Country Code, Region, IncomeGroup, SpecialNotes, TableName lgl (1): ...6
## ℹ Use `spec()` to retrieve the full column specification for this data. ℹ
## Specify the column types or set `show_col_types = FALSE` to quiet this message.
## • `` -> `...6`
names(meta_cty)
## [1] "Country Code" "Region"       "IncomeGroup"  "SpecialNotes" "TableName"   
## [6] "...6"
#Identify year columns
year_cols <- names(main)[stringr::str_detect(names(main), "^[0-9]{4}$")]

df_long <- main %>%
dplyr::select("Country Name", "Country Code", "Indicator Name", "Indicator Code",tidyselect::all_of(year_cols)) %>%
tidyr::pivot_longer(
cols = tidyselect::all_of(year_cols),
names_to = "year",
values_to = "value"
) %>%
dplyr::mutate(year = as.integer(year))

# Attach Region & IncomeGroup
meta_cty_small <- meta_cty %>%
dplyr::select("Country Code", "Region", "IncomeGroup")

df_long <- df_long %>%
dplyr::left_join(meta_cty_small, by = "Country Code")

Global overview

#Coverage by year
avail_by_year <- df_long %>%
dplyr::group_by(year) %>%
dplyr::summarise(
n_countries = sum(!is.na(value)),
.groups = "drop"
)

knitr::kable(
head(avail_by_year, 10),
caption = "Number of economies with data by year (first 10 years)."
)
Number of economies with data by year (first 10 years).
year n_countries
1960 0
1961 0
1962 0
1963 0
1964 0
1965 0
1966 0
1967 0
1968 0
1969 0

#Latest year with data

latest_year <- df_long %>%
dplyr::filter(!is.na(value)) %>%
dplyr::summarise(latest_year = max(year)) %>%
dplyr::pull(latest_year)

latest <- df_long %>%
dplyr::filter(year == latest_year, !is.na(value))

global_desc <- latest %>%
dplyr::summarise(
count = dplyr::n(),
mean = mean(value),
sd = sd(value),
min = min(value),
p10 = stats::quantile(value, 0.10),
p25 = stats::quantile(value, 0.25),
p50 = stats::quantile(value, 0.50),
p75 = stats::quantile(value, 0.75),
p90 = stats::quantile(value, 0.90),
max = max(value)
)

knitr::kable(global_desc, digits = 2,
caption = paste("Global distribution in", latest_year))
Global distribution in 2023
count mean sd min p10 p25 p50 p75 p90 max
232 22.88 23.01 0.01 0.97 2.71 14.38 40.97 59.98 92.02

#World average per year

world_series <- df_long %>%
dplyr::group_by(year) %>%
dplyr::summarise(
value = mean(value, na.rm = TRUE),
.groups = "drop"
) %>%
dplyr::mutate(series = "World average")

#Sub-Saharan Africa average

ssa_series <- df_long %>%
dplyr::filter(Region == "Sub-Saharan Africa") %>%
dplyr::group_by(year) %>%
dplyr::summarise(
value = mean(value, na.rm = TRUE),
.groups = "drop"
) %>%
dplyr::mutate(series = "Sub-Saharan Africa average")

#Kenya series

kenya_series <- df_long %>%
dplyr::filter('Country Code' == "KEN") %>%
dplyr::group_by(year) %>%
dplyr::summarise(
value = mean(value, na.rm = TRUE),
.groups = "drop"
) %>%
dplyr::mutate(series = "Kenya")

ts_all <- dplyr::bind_rows(world_series, ssa_series, kenya_series)

ggplot(ts_all, aes(x = year, y = value, colour = series)) +
geom_line(linewidth = 1.1) +
labs(
title = "Female employment in agriculture: Kenya vs Sub-Saharan Africa vs World",
x = "Year",
y = "Female employment in agriculture (% of female employment)",
colour = NULL
) +
theme_minimal(base_size = 11)
## Warning: Removed 64 rows containing missing values or values outside the scale range
## (`geom_line()`).

Regional support past year

# Kenya latest (could be length 0 if no data)
kenya_latest_vec <- latest %>%
  dplyr::filter(`Country Code` == "KEN") %>%
  dplyr::pull(value)

kenya_latest <- if (length(kenya_latest_vec) == 0) NA_real_ else kenya_latest_vec[1]

# SSA stats (returning 1 row by construction)
ssa_stats <- latest %>%
  dplyr::filter(Region == "Sub-Saharan Africa") %>%
  dplyr::summarise(
    mean_ssa = mean(value, na.rm = TRUE),
    min_ssa  = min(value, na.rm = TRUE),
    max_ssa  = max(value, na.rm = TRUE)
  )

ssa_mean <- ssa_stats$mean_ssa[[1]]
ssa_min  <- ssa_stats$min_ssa[[1]]
ssa_max  <- ssa_stats$max_ssa[[1]]

summary_tbl <- data.frame(
  indicator = c("Kenya", "SSA mean", "SSA min", "SSA max"),
  value     = c(kenya_latest, ssa_mean, ssa_min, ssa_max)
)

knitr::kable(summary_tbl, digits = 2,
             caption = paste("Kenya and Sub-Saharan Africa in", latest_year))
Kenya and Sub-Saharan Africa in 2023
indicator value
Kenya 34.25
SSA mean 44.30
SSA min 3.16
SSA max 92.02

latest_reg <- latest %>%
dplyr::filter(!is.na(Region)) %>%
dplyr::group_by(Region) %>%
dplyr::summarise(
value = mean(value, na.rm = TRUE),
.groups = "drop"
) %>%
dplyr::arrange(dplyr::desc(value))

ggplot(latest_reg,
aes(x = reorder(Region, value), y = value)) +
geom_col(fill = "steelblue") +
coord_flip() +
labs(
title = paste("Female agricultural employment by region,", latest_year),
x = "Region",
y = "Female employment in agriculture (% of female employment)"
) +
theme_minimal(base_size = 11)

Country Typology

country_trends <- df_long %>%
  arrange(`Country Code`, year) %>%
  group_by(`Country Name`, `Country Code`) %>%
  summarise(
    first_year = min(year[!is.na(value)]),
    last_year  = max(year[!is.na(value)]),
    first_val  = {
      v <- value[!is.na(value)]
      if (length(v) == 0) NA_real_ else v[1]
    },
    last_val   = {
      v <- value[!is.na(value)]
      if (length(v) == 0) NA_real_ else v[length(v)]
    },
    abs_change = last_val - first_val,
    annual_change = ifelse(last_year > first_year,
                           abs_change / (last_year - first_year),
                           NA_real_),
    .groups = "drop"
  )
## Warning: There were 62 warnings in `summarise()`.
## The first warning was:
## ℹ In argument: `first_year = min(year[!is.na(value)])`.
## ℹ In group 6: `Country Name = "American Samoa"` `Country Code = "ASM"`.
## Caused by warning in `min()`:
## ! no non-missing arguments to min; returning Inf
## ℹ Run `dplyr::last_dplyr_warnings()` to see the 61 remaining warnings.
classify <- function(first_val, last_val, abs_change,
thresh_high = 50, thresh_low = 10) {
if (is.na(abs_change)) return("no_data")
if (!is.na(first_val) && !is.na(last_val) &&
first_val >= thresh_high && last_val < thresh_low) {
return("deep_structural_shift")
}
if (abs_change <= -20) return("large_decline")
if (abs_change >= 10) return("rising_feminisation")
if (abs(abs_change) < 5) return("stable")
"moderate_change"
}

country_trends <- country_trends %>%
dplyr::rowwise() %>%
dplyr::mutate(
trajectory_type = classify(first_val, last_val, abs_change)
) %>%
dplyr::ungroup()

trajectory_summary <- country_trends %>%
dplyr::count(trajectory_type, name = "n_countries")

knitr::kable(
trajectory_summary,
caption = "Number of countries by female agricultural employment trajectory type."
)
Number of countries by female agricultural employment trajectory type.
trajectory_type n_countries
deep_structural_shift 1
large_decline 51
moderate_change 111
no_data 31
rising_feminisation 3
stable 69

Discussion

Female employment in agriculture has declined steadily across the world, but the pace and depth of this transition differ sharply by country and region. In 2023, the median country had only about 14–15 percent of employed women in agriculture, yet the distribution remains highly skewed: the 90th percentile is around 60 percent and the maximum exceeds 92 percent, indicating that a small group of economies still relies overwhelmingly on women’s agricultural work. This divergence suggests that global averages can conceal a dual reality: many countries have largely completed the agricultural transition, while others remain heavily dependent on women’s farm labour for both livelihoods and food security. ​

Regional patterns underscore this duality, with Sub‑Saharan Africa and South Asia standing out as the only large regions where around 44–45 percent of employed women are still in agriculture in the most recent year. In contrast, Europe & Central Asia averages about 11 percent, Latin America & Caribbean about 7 percent, and North America under 1 percent, reflecting long‑established shifts into services and industry in richer regions. These gaps matter for policy because they map onto differences in demographic structure, informality, and climate vulnerability, implying that strategies to support women’s economic empowerment must be calibrated very differently in agrarian versus post‑agrarian regions. ​

Kenya exemplifies an intermediate trajectory within this landscape: in 2023, approximately 34.2 percent of employed Kenyan women worked in agriculture, compared with a Sub‑Saharan African average of about 44.3 percent and a global mean of roughly 22.9 percent. This places Kenya below its regional peers in terms of female agrarian dependence, yet still more than double the global median, highlighting both progress and continued structural reliance on agriculture. Trend estimates over the last two decades indicate a faster decline in Kenya’s female agricultural share than in Sub‑Saharan Africa overall, pointing to a relatively dynamic shift into non‑farm work and underlining a dual policy agenda: boosting productivity and resilience for the roughly one‑third of employed women who remain in agriculture, while investing in skills, childcare, infrastructure, and finance to ensure that those exiting farming move into decent, higher‑productivity jobs rather than low‑wage informal activities.