In this document we estimate the talent pool factoring in the changing levels of interest in the game. Baseball started as a game played by people largely from the Northeast (NE) and Midwest (MW) regions of the United States of America. Our construction of the talent pool will be pegged to the population of age 20-29 white males from the NE and MW region of the United States of America. Simply stated, the talent pool will be \[ \frac{\text{NE and MW region populations of age 20-29 white males}}{\text{proportion of white MLB players from NE and MW regions}} \times \text{adjustment}. \] Adjustments include the effects of changing interest in baseball, wars, segregation, gradual integration of the MLB, and demographic differences in reaching the MLB. In our analysis, the states that comprise the NE and MW regions are: Connecticut, Delaware, Illinois, Indiana, Iowa, Kansas, Maine, Massachusetts, Michigan, Minnesota, Nebraska, New Hampshire, New Jersey, New York, North Dakota, Ohio, Pennsylvania, Rhode Island, South Dakota, Vermont, and Wisconsin.

Previous versions of our talent pool calculation did not restrict the eligible population to white males. The reason for this change is that, in this document, we also provide an estimate for the Negro League talent pool (1920–1948). Our estimate for the Negro League talent pool is based on the share of Black MLB players relative to white MLB players post-integration. Because of this, our estimate necessarily involves comparing the population counts of Black males to white males in the broader US population. The need for this approach is most clearly illustrated by Armour (2007) and Armour and Levitt (2016), which show that the MLB shares of Black players relative to white players were far greater than basic population demographics alone would predict.

We load in the necessary software packages used in this analysis.

library(Lahman)
library(tidyverse)
library(ggplot2)
library(splines)
library(readxl)

List of Topics

MLB Demographics

We load in the Batting and Pitching data sets in the Lahman R package and isolate the birth state and birth country for every MLB player in history (as recorded by the Lahman Database and implemented in the Lahman R package). Missing entries are discarded.

foo_bat = Batting %>% 
  dplyr::select(playerID, yearID) %>% 
  left_join(People %>% dplyr::select(playerID, birthCountry, birthState))
foo_pit = Pitching %>% 
  dplyr::select(playerID, yearID) %>% 
  left_join(People %>% dplyr::select(playerID, birthCountry, birthState))

## adjust for missingness
foo_tot = rbind(foo_bat, foo_pit) %>% distinct()
foo_tot[is.na(foo_tot$birthCountry), ]$birthCountry = "missing"
foo_tot[!is.na(foo_tot$birthCountry) & 
          is.na(foo_tot$birthState), ]$birthState = "missing"

We load in racial demographics data from Rob Arthur’s 2024 article, As the World Series approaches, baseball still struggles with racial bias. This data contains predicted race for roughly 40,000 baseball players from 1950-2019. Per Arthur,

Using the racial classifications of 11,000 major league players painstakingly collected by hand by baseball researchers Mark Armour and Dan Levitt, I built an artificial intelligence model based on players’ faces and names to identify their perceived race. While the model could not say how a player might self-identify, it predicted how an outside human research assistant would guess their racial background about as accurately (94%) as another human would. I ran the model on all players with headshots and names in major and minor league history from 1950 to 2019, which amounted to about 40,000 players.

We isolate the predicted race for each MLB player. We then incorporate the birth state and country data into this demographic dataset.

faces = read_csv("../../talent-pool/final_merged.csv")
race_state_MLB = faces %>% 
  filter(!is.na(key_retro)) %>% 
  group_by(key_retro) %>% 
  summarise(race = unique(pred_race)) %>% 
  ungroup() %>% 
  left_join(foo_tot %>% left_join(People %>% select(playerID, retroID) %>% 
                                    rename(key_retro = retroID)))

Here we encode regions based on birth state, and then calculate the proportion of MLB players from the Midwest and North East regions who are White.

## regional information for MLB racial data
race_region_MLB = race_state_MLB %>% 
  mutate(region = ifelse(birthState %in% c("CT", "MA", "DE", "ME", "NH", 
                                           "NJ", "NY", "PA", "VT", "RI"), "NE", "0"), 
         region = ifelse(birthState %in% c("IL", "IN", "MI", "OH", "WI", 
                                           "IA", "KS", "MN", "MO", "NE", "ND", "SD"), 
                         "MW", region), 
         region = ifelse(birthState %in% c("WA", "MT", "ID", "WY", "OR", 
                                           "CA", "NV", "UT", "CO", "AZ", 
                                           "NM"), "W", region), 
         region = ifelse(birthCountry == "USA" & region == "0", "S", region), 
         region = ifelse(region == "0", "INTL", region))

## proportion of MLB that is from MW and NE and is White
prop_white_MW_NE_MLB = race_region_MLB %>% 
  group_by(yearID) %>% 
  summarise(prop_white_MW_NE_MLB = mean(race == "White" & region %in% c("MW", "NE"))) %>% 
  as.data.frame()
prop_white_MW_NE_MLB[155, ] = c(2025, mean(prop_white_MW_NE_MLB[153:154, 2]))

We can see a decline in the proportion of MLB players from the MW and NE regions who are White. The demographic change is massive. In the early eras this proportion was nearly 0.80 while it is nearly 0.15 around 2025.

prop_white_MW_NE_MLB %>% 
  ggplot() + 
  aes(x = yearID, y = prop_white_MW_NE_MLB) + 
  geom_line() + 
  ylim(0, 1) + 
  theme_minimal() + 
  labs(title = "Proportion of MLB that is from MW and NE and is White", 
       subtitle = "(1871-2025)",
       x = "Year", 
       y = "Proportion")

Back to topics.

Census Data

We now obtain census population totals for the counts of US aged 20-29 males from 1871-2025 broken across Black and White tallies. Links to resources are working through December 2025. Note that the tally of aged 20-29 Black males will not be included because this demographic group will not be used to calculate the talent pool.

# https://www2.census.gov/library/publications/decennial/1870/vital-statistics/1870b-33.pdf
US1870_white = 1.255 + 1.328 # page 6
totalM1870 = 19.493 # page 5
total1870 = 38.5556 # page 5
propM1870 = US1870_white/totalM1870
prop1870 = US1870_white/total1870

# https://www2.census.gov/library/publications/decennial/1880/vol-01-population/1880_v1-15.pdf
US1880_white = 2.219 + 1.838 # page 2  
totalM1880 = 25.518
total1880 = 50.189 # see census1890
propM1880 = US1880_white/totalM1880
prop1880 = US1880_white/total1880

# https://www2.census.gov/library/publications/decennial/1900/volume-2/volume-2-p5.pdf
## We did not find the relevant population totals for 1890 
## We compute the average of 1880 and 1900 as an educated guess.
US1900_white = 3.793 + 3.366 # native whites, page 3
US1890_white = mean(c(US1880_white,US1900_white))
total1900 = 76.303
total1890 = 62.980

# https://www2.census.gov/library/publications/decennial/1910/volume-1/volume-1-p6.pdf
US1910_white = 4.071 + 3.792 # page 15  
totalM1910 = 47.333
total1910 = 91.972
propM1910 = US1910_white/totalM1910
prop1910 = US1910_white/total1910

# https://www2.census.gov/library/publications/decennial/1920/volume-2/41084484v2ch03.pdf
US1920_black = 0.487169 + 0.424352 # page 14
US1920_white = 4.019 + 4.094 # page 14
totalM1920 = 53.900
total1920 = 105.711
propM1920 = (US1920_black + US1920_white)/totalM1920
prop1920 = (US1920_black + US1920_white)/total1920

# https://www2.census.gov/library/publications/decennial/1930/population-volume-2/16440598v2ch11.pdf
US1930_black = 0.553622 + 0.500520 # page 18
US1930_white = 4.666 + 4.247  
totalM1930 = 55.17
total1930 = 108.86
propM1930 = (US1930_black + US1930_white)/totalM1930
prop1930 = (US1930_black + US1930_white)/total1930

# https://www2.census.gov/library/publications/decennial/1940/population-volume-4/33973538v4p1ch1.pdf 
US1940_black = 0.120615 + 0.117716 + 0.115437 + 0.111106 + 0.113876 + 0.118848 + 
  0.108433 + 0.107656 + 0.116749 + 0.106953 # page 9
US1940_white = 1.030 + 1.061 + 1.008 + 1.005 + 1.010 + 
  1.006 + 0.988 + 0.976 + 0.974 + 0.948 # page 9
totalM1940 = 66.062 # page 9
total1940 = 131.667 # page 9
propM1940 = (US1940_black + US1940_white)/totalM1940
prop1940 = (US1940_black + US1940_white)/total1940

# https://www2.census.gov/library/publications/decennial/1950/population-volume-2/21983999v2p1ch2.pdf
# https://www2.census.gov/library/publications/decennial/1950/pc-14/pc-14-05.pdf
US1950_black = 0.603511 + 0.622371 # page 1
US1950_white = 5.003 + 5.350 # page 1
totalM1950 = 74.833
total1950 = 150.697
propM1950 = (US1950_black + US1950_white)/totalM1950
prop1950 = (US1950_black + US1950_white)/total1950

# https://www.cdc.gov/nchs/data/dvs/pop6097.pdf
US1960_black = 0.571 + 0.552
US1960_white = 4.646 + 4.722

# https://www.census.gov/data/tables/time-series/demo/popest/1970s-state.html
foo = read_excel("population-data/pe-19.xlsx")
US1970_black = foo %>% 
  filter(`Race/Sex Indicator` == "Black male", `Year of Estimate` == 1970) %>% 
  mutate(age2029 = `20 to 24 years` + `25 to 29 years`) %>% 
  pull(age2029) %>% 
  sum() / 1e6
US1970_white = foo %>% 
  filter(`Race/Sex Indicator` == "White male", `Year of Estimate` == 1970) %>% 
  mutate(age2029 = `20 to 24 years` + `25 to 29 years`) %>% 
  pull(age2029) %>% 
  sum() / 1e6

# https://babel.hathitrust.org/cgi/pt?id=umn.31951d02527887v&seq=3
US1980_black = 1.300 + 1.084
US1980_white = 8.680 + 8.004

# The 1977 standards required federal agencies to report race-specific tabulations using 
#four single-race categories: American Indian or Alaskan Native, Asian or Pacific 
#Islander, Black, and White. Under the 1977 standards, race and ethnicity were considered 
#to be two separate and distinct concepts. For this reason, people of Hispanic origin may 
#be of any race.

# https://www.nber.org/research/data/us-intercensal-county-population-data-age-sex-race-and-hispanic-origin
# https://data.nber.org/census/population/popest/1990/desc/stch1990/desc.txt
foo = read_csv("population-data/stch1990.csv")
US1990_black = foo %>% 
  filter(agegroup %in% c(5,6), year == 1990, racesex == 3) %>% 
  pull(pop) %>% 
  sum() / 1e6
US1990_white = foo %>% 
  filter(agegroup %in% c(5,6), year == 1990, racesex == 1) %>% 
  pull(pop) %>% 
  sum() / 1e6


#The question on race on the 2000 census was based on OMB’s 1997 “Revisions to the 
#Standards for the Classification of Federal Data on Race and Ethnicity”...
#As a result, under the 1997 standards, as under the 1977 standards, people of Hispanic 
#origin may be of any race.

# https://www2.census.gov/programs-surveys/decennial/2000/phc/phc-t-08/tab03.pdf
US2000_black = 1.342 + 1.263 ## black in combination
# https://www2.census.gov/programs-surveys/decennial/2000/phc/phc-t-08/tab02.pdf
US2000_white = 6.897 + 7.050  ## white in combination

# See here for birth information to support 2020 dropoff: 
# https://embryology.med.unsw.edu.au/embryology/index.php/USA_Statistics

#Similar to race data on the 2000 census, the question on race on the 2010 census was 
#based on OMB’s 1997 “Revisions to the Standards for the Classification of Federal Data on
#Race and Ethnicity”

# https://www.census.gov/data/tables/2010/demo/age-and-sex/2010-age-sex-composition.html
US2010_black = 1.534 + 1.466 ## black in combination (table 5)
US2010_white = 8.566 + 8.807 ## white in combination (table 3)

## 2020
# https://www.census.gov/data/tables/time-series/demo/popest/2020s-national-detail.html
foo = read_csv("population-data/nc-est2024-alldata-r-file01.csv")
US2020_black = foo %>% select(UNIVERSE, MONTH, AGE, YEAR, BAC_MALE) %>% 
  filter(AGE >= 20, AGE <= 29) %>% 
  filter(MONTH < 5) %>% 
  summarise(pop = sum(BAC_MALE)) / 1e6
US2020_white = foo %>% select(UNIVERSE, MONTH, AGE, YEAR, WAC_MALE) %>% 
  filter(AGE >= 20, AGE <= 29) %>% 
  filter(MONTH < 5) %>% 
  summarise(pop = sum(WAC_MALE)) / 1e6

## 2025
# https://www.census.gov/data/tables/time-series/demo/popest/2020s-national-detail.html
foo = read_csv("population-data/nc-est2024-alldata-r-file12.csv")
US2025_black = foo %>% select(UNIVERSE, MONTH, AGE, YEAR, BAC_MALE) %>% 
  filter(AGE >= 20, AGE <= 29) %>% 
  filter(MONTH == 12) %>% 
  summarise(pop = sum(BAC_MALE)) / 1e6
US2025_white = foo %>% select(UNIVERSE, MONTH, AGE, YEAR, WAC_MALE) %>% 
  filter(AGE >= 20, AGE <= 29) %>% 
  filter(MONTH == 12) %>% 
  summarise(pop = sum(WAC_MALE)) / 1e6
total2025 = 
  foo %>% filter(MONTH == 12, AGE == 999) %>% 
  pull(TOT_POP) %>% 
  unlist()
prop2025 = (US2025_black + US2025_white)/(total2025 / 1e6)

## aged 20-29 male Census counts split across white and black
US1870_black = US1880_black = US1890_black = US1900_black = US1910_black = 0
race_demo_initial = data.frame(year = c(1870 +0:15 * 10, 2025),
                               black = unlist(c(US1870_black, US1880_black, US1890_black, US1900_black, 
                                                US1910_black, US1920_black, US1930_black, US1940_black, 
                                                US1950_black, US1960_black, US1970_black, US1980_black, 
                                                US1990_black, US2000_black, US2010_black, US2020_black, 
                                                US2025_black)), 
                               white = unlist(c(US1870_white, US1880_white, US1890_white, US1900_white, 
                                                US1910_white, US1920_white, US1930_white, US1940_white, 
                                                US1950_white, US1960_white, US1970_white, US1980_white, 
                                                US1990_white, US2000_white, US2010_white, US2020_white, 
                                                US2025_white))) 

## interpolation for all years 1871-2025
race_demo = data.frame(year = 1870:2025, 
                       black = c(rep(0, 1920-1870), 
                                 approx(race_demo_initial$year[-c(1:5)], 
                                        race_demo_initial$black[-c(1:5)], 
                                        xout = 1920:2025)$y),
                       white = approx(race_demo_initial$year, race_demo_initial$white, 
                                      xout = 1870:2025)$y)
race_demo %>% 
  ggplot() + 
  geom_line(aes(x = year, y = white, color = "White")) +
  geom_line(aes(x = year, y = black, color = "Black")) +
  scale_color_manual(values = c("White" = "blue", 
                                "Black" = "red"),
                     name = "Race") +
  theme_minimal() + 
  labs(title = "Census Counts of Aged 20–29 Males from 1870–2025",
       subtitle = "Counts are in millions",
       x = "Year",
       y = "Count")

Back to topics.

Midwest and North East Regions

We now obtain regional census totals for US regions. Particular interest is in the Midwest and North East regions which define our talent pool.

## Get USA population and populations of regions (need to adjust above for MW and NE)
#https://www.census.gov/data/tables/time-series/dec/popchange-data-text.html
#gsub(" \t|\n" ,", ", gsub(",","", c("57,609,148    55,317,240  53,594,378  
# 50,809,229    49,135,283  49,040,703  44,677,819  39,477,986  35,976,777  
# 34,427,091    29,662,053  25,868,573 68,985,454   66,927,001  64,392,776  
# 59,668,632    58,865,670  56,571,663  51,619,139  44,460,762  40,143,332  
# 38,594,100    34,019,792  29,888,542 126,266,107  114,555,744     100,236,820     
# 85,445,930    75,372,362  62,795,367  54,973,113  47,197,088  41,665,901  
# 37,857,633    33,125,803  29,389,330 78,588,572   71,945,553  63,197,932  
# 52,786,082    43,172,490  34,804,193  28,053,104  20,189,962  14,379,119  
# 12,323,836    9,213,920   7,082,086")))
mat = cbind(seq(2020,1910,by=-10),
            matrix(c(57609148, 55317240, 53594378, 50809229, 49135283, 
                     49040703, 44677819, 39477986, 35976777, 34427091, 
                     29662053, 25868573, 68985454, 66927001, 64392776, 
                     59668632, 58865670, 56571663, 51619139, 44460762, 
                     40143332, 38594100, 34019792, 29888542, 126266107, 
                     114555744, 100236820, 85445930, 75372362, 62795367, 
                     54973113, 47197088, 41665901, 37857633, 33125803, 
                     29389330, 78588572, 71945553, 63197932, 52786082, 
                     43172490, 34804193, 28053104, 20189962, 14379119, 
                     12323836, 9213920, 7082086), ncol = 4))
df = as.data.frame(mat)
colnames(df) = c("year","NE","MW","S","W")
df$total = rowSums(df[, 2:5])
# use same regional proportions from 2020 for 2025 data
df = rbind(unlist(c(2025, round(df[1, 2:5] / df[1, 6] * total2025), total2025)), 
           df)
#https://www2.census.gov/library/publications/decennial/1870/population/1870a-04.pdf
NE1870 = 540000 + 130000 + 630000 + 1460000 + 320000 + 910000 + 
  4380000 + 3520000 + 220000 + 330000
# "IL", "IN", "IA", "KS", "MI", "MN", "MO", "NE", "ND", "OH", "SD", "WI", 
MW1870 = 2540000 + 1680000 + 1190000 + 360000 + 1180000 + 440000 + 1720000 + 
  120000 + 2670000 + 1050000
#"AZ", "CA", "CO", "ID", "MT", "NM", "OR", "NV", "UT", "WA", "WY" 
W1870 = 200000 + 560000 + 100000 + 100000
df = rbind(df, c(1900, NA, NA, NA, NA, total1900*1e6), 
           c(1890, NA, NA, NA, NA, total1890*1e6), 
           c(1880, NA, NA, NA, NA, total1880*1e6),
           c(1870, NE1870, MW1870, total1870*1e6 - W1870 - NE1870 - MW1870, W1870, total1870*1e6))

df_prop = rbind(cbind(df[1:13, 1],  df[1:13, 2:5] / df[1:13, 6]),
                as.numeric(cbind(1870, df[17, 2:5] / df[17,6])))
colnames(df_prop)[1] = "year"

x1 = approx(c(1910,1870), tail(df_prop$NE,2), xout = seq(1900,1880,by=-10))$y
x2 = approx(c(1910,1870), tail(df_prop$MW,2), xout = seq(1900,1880,by=-10))$y
x3 = approx(c(1910,1870), tail(df_prop$S,2), xout = seq(1900,1880,by=-10))$y
x4 = approx(c(1910,1870), tail(df_prop$W,2), xout = seq(1900,1880,by=-10))$y
df_prop[14:16, 2] = x1
df_prop[14:16, 3] = x2
df_prop[14:16, 4] = x3
df_prop[14:16, 5] = x4
df_prop[16, ] = as.numeric(cbind(1870, df[17, 2:5] / df[17,6]))
df_prop[14:16, 1] = c(1900, 1890, 1880)
## check to make sure that the proportions sum to 1
#rowSums(df_prop[, 2:5])
df[14:16, 2:5] = df_prop[14:16, 2:5] * df[14:16, 6]

From here we obtain the proportion of the USA that is from each region.

df_long = pivot_longer(df, cols = c("NE", "MW", "S", "W", "total"), 
                       names_to = "region", values_to = "population")

df_long_inter = do.call(rbind, tapply(df_long, INDEX = as.factor(df_long$region), FUN = function(x) {
  data.frame(yearID = 1870:2025, 
             region = unique(x$region),
             pop = approx(x$year, x$population, xout = 1870:2025)$y
             )
})) %>% group_by(yearID) %>% 
  ## multiply by 2 because total regional population count is included
  mutate(pop_perc = pop / sum(pop) * 2)

We also obtain the proportions of MLB players from each region.

## get proportions of people from combinations of regions (MW and NE)
NMLB = foo_tot %>% group_by(yearID) %>% 
  summarise(N = n())

state_perc = foo_tot %>% 
  group_by(yearID, birthState, birthCountry) %>% 
  summarise(Nstate = n()) %>%
  distinct() %>%
  left_join(NMLB) %>% 
  mutate(state_perc = Nstate/N) %>% 
  mutate(region = ifelse(birthState %in% c("CT", "MA", "DE", "ME", "NH", 
                                           "NJ", "NY", "PA", "VT", "RI"), "NE", "0"), 
         region = ifelse(birthState %in% c("IL", "IN", "MI", "OH", "WI", 
                                           "IA", "KS", "MN", "MO", "NE", "ND", "SD"), 
                         "MW", region), 
         region = ifelse(birthState %in% c("WA", "MT", "ID", "WY", "OR", 
                                           "CA", "NV", "UT", "CO", "AZ", 
                                           "NM"), "W", region), 
         region = ifelse(birthCountry == "USA" & region == "0", "S", region), 
         region = ifelse(region == "0", "INTL", region))

region_perc = state_perc %>% group_by(yearID, region) %>% 
  summarise(region_perc = sum(state_perc))


region_perc_pop = region_perc %>% 
  left_join(df_long_inter) %>% 
  filter(yearID <= 2025) %>% 
  group_by(yearID) %>% 
  summarise("NEpMW_MLB" = sum(region_perc[region %in% c("NE","MW")], na.rm = TRUE), 
            "SpW_MLB" = sum(region_perc[region %in% c("S","W")], 
                            na.rm = TRUE),
            "SpWpINTL_MLB" = sum(region_perc[!region %in% c("NE","MW")], 
                                 na.rm = TRUE), 
            "NEpMW_pop" = sum(pop[region %in% c("NE","MW")], na.rm = TRUE), 
            "SpW_pop" = sum(pop[region %in% c("S","W")], na.rm = TRUE), 
            "SpWpINTL_pop" = sum(pop[!region %in% c("NE","MW")], na.rm = TRUE), 
            "NEpMW_pop_prop" = sum(pop_perc[region %in% c("NE","MW")], na.rm = TRUE), 
            "SpW_pop_prop" = sum(pop_perc[region %in% c("S","W")], na.rm = TRUE), 
            "INTL" = sum(region_perc[region %in% c("INTL")], na.rm = TRUE))

Note that the above follows similar steps to what was done using the racial demographic data. However, that data contained a few missing records.

## Lahman only
dim(state_perc)
## [1] 11802     7
## Lahman + racial demographic data
state_perc_race = race_region_MLB %>% 
  group_by(yearID, birthState, birthCountry) %>% 
  summarise(Nstate = n()) %>%
  distinct()
dim(state_perc_race)
## [1] 10028     4

Back to topics.

Adjustments

We now apply a series of adjustments to the talent pool that account for exogenous factors which affect the size of the MLB talent pool. These include: changing interest in baseball; wars that significantly drained the talent pool; rates of racial integration beginning in 1947.

Back to topics.

Interest Adjustment

We will first adjust the talent pool for changes in baseball interest over time. We will use these sources:

  • Gallup polling data on the question: what is your favorite sport? This survey ranges from 1937-2017. Source
  • Gallup polling data on general baseball interest stratified by age/gender. This survey was conducted in 1937, 1952, and 2001. We will use information from the “Fan or Follower of Professional/Major League Baseball?” graphic for males aged 19-29. Source
  • Harris polling data on favorite sports. This survey ranges from 1985-2016. Source 1 and Source 2
  • Harris polling data on the question: are you a fan or follower of this sport? Source

The Harris and Gallup polling data on general baseball interest (are you a fan/follower of baseball) indicates that baseball interest has been relatively constant throughout the years, although it has deceased. However, the proportion of Americans who view baseball as their favorite sport has dramatically fallen. Note that Harris reports a higher proportion of the population whose favorite sport is baseball than Gallup. We will average the survey results. We will then define interest in baseball as the average of general baseball interest and those who consider baseball their favorite sport. This reflects the fact that some MLB players list other sports as their favorite (For example, Tony Gwynn loved basketball before baseball). Other aggregations will be considered in the Appendix (75% favorite sport is baseball and 25% general baseball interest; 100% favorite sport is baseball).

We could not find survey data about baseball interest prior to 1937. We will set baseball interest at 0.20, 0.20, 0.22, 0.30, and 0.38 respectively for years 1870, 1876, 1886, 1920, and 1930. We have endeavored to make reasonable choices for interest levels of young white adult males towards baseball over time, starting in the 1870s into the current era. This starting point of interest level for 1870 aims to balance the geographic area where the sport was played and increasing awareness from greater organization and media coverage of professional baseball. Indeed, our aim is looking at what conditions influence the interest of the generation of young white males that shape their fandom or even aspiration of becoming a ballplayer and how that increases and decreases over time. Thus, formation of the National League in 1876 would spur interest. So would the emergence of Babe Ruth in 1919-1920 not only as a home-run slugger but also as the well-covered “Sultan of Swat,” a media sensation whose popularity was aided by the newsprint media.

In a certain sense, we are generous in placing the 1870 interest level among the white male population interested in baseball at 20 percent. Baseball salaries were far lower in the past, media exposure was far less than it is in more modern eras, and baseball teams would disband with some frequency in the older eras. These early era realities may negatively effect one’s interest in pursuing a career in baseball. Our analysis does not make any explicit adjustments for changing salaries for MLB salaries, but it does explicitly account for increased competition from other sports. A thorough accounting for changing salaries is beyond the scope of this work, but it may have a considerable negative effect on the population pursuing a career in the MLB prior to more modern times. As recently as 1967, the MLB minimum salary was $6000 and the MLB average salary was $19,000 while the median household income was $7200. In 2022 the real median income is roughly $75,000 while the MLB minimum salary is $700,000 and the MLB average salary is roughly $4,000,000. Before 1967, detailed salary data becomes sparse. This article reports that the average MLB salary in 1920 was $5000 which is less than double the median household income at the time which was about $3300.

However, it can be said that baseball may be a source of social mobility for lower-class men even though MLB salaries were lower in the past. Riess (1980) studied professional baseball and social mobility in the Progressive era. He concluded that professional baseball was greatly overrated as a source of upward mobility when the game was at its unchallenged height, and that MLB jobs went mostly to well-educated, middle-class native American whites, Irishmen, and Germans who utilized the sport as a means of maintaining their social status and planned to use it as a ladder to future success. In summarizing Riess’s 1980 book Touching Base, Gerlach (1994) stated that the depiction of baseball as an “all-American game embodying all American virtues and values” was the prescriptive construct of a burgeoning baseball business geared to and supported by a native-born middle class.

It should be noted that there were more professional opportunities to play baseball in the past even though MLB salaries were lower, and that the relatively fewer professional opportunities that exist today may reflect a fundamental lack of interest in reaching the MLB that is not captured by surveys. In a study of structural mutualism–cooperative behavior among teams to the benefit of each due to the benefit of their membership in leagues–with respect to minor league baseball team and league foundings and disbandings, Land, Davis, and Blau (1994) charted the density of minor leagues and minor league teams. This chart clearly revealed a dramatic decrease in minor league operations after a pronounced post-WWII peak. The number of teams (leagues) was at 448 (59) in 1949, and fell to 132 (20) in 1964 (see here for details). As noted by Land, Davis, and Blau (1994), Sullivan’s 1990 book The Minors attributed this decline in the minor leagues to relocation of MLB teams to minor league markets and the spread of television broadcasting games. Bellamy and Walker (2004) noted that television went from 0.4 percent of U.S. households in 1948 to 87.1 percent in 1960. However, these authors concluded that the extension of MLB radio broadcasts, both national and local, in combination with a market correction, probably hurt the Minor Leagues, particularly in the first half of the 1950s, much more than the televised broadcasts that were in their infancy.

Land, Davis, and Blau (1994) stated that: “the single most important event in the history of the minors occurred in 1920s, with the implementation of the farm system…This system allowed the Cardinals to field extremely competitive teams without having to pay high prices to the minor-league clubs that owned the player’s contracts. The New York Yankees soon adopted this strategy and dominated the AL in the 1930s. It is not clear to what extent other teams wanted, or were able, to use this system during the 1930s, but it clearly was common.” Horowitz (1997) studied competitive balance in the MLB and speculated that “the owners, however, solely for business purposes, embraced expansion and allowed their lust for broadcast-rights revenues to hasten the erosion of the minor leagues and their farm systems.” However, footnote 9 in Land, Davis, and Blau (1994) stated that the majority of minor league teams that died were independent teams not affiliated with an MLB farm system.

In aggregate, it appears that collapse of professional baseball (proxied by the Minors) is a mere shuffling around and does not reflect some deep collapse in the talent pool. Thus, the rapid contraction of professional opportunities (proxied by the Minor Leagues) can be explained, albeit not completely, by factors (relocation of MLB teams to minor league markets, extensions of MLB radio and television broadcasts, a possible market correction, and structural mutualism) that do not necessarily signal a corresponding rapid decrease in interest in playing baseball professionally which would not be captured by surveys. Moreover, per game attendance has steadily risen over time with some peaks and valleys corresponding to historical events. That being said, in the Appendix we will consider an estimate of the talent pool in which interest in baseball is higher during the years preceding the erosion of the minor leagues.

MLBattendance = read_csv("MLBattendance.csv")
colnames(MLBattendance)[3] = "AttendPerGame"
MLBattendance %>%
  ggplot() +
  aes(x = Year, y = AttendPerGame) +
  geom_line() +
  theme_minimal() +
  labs(title = "Attendance per game per year") +
  geom_vline(xintercept = 1919, lty = 2) +
  geom_vline(xintercept = 1928, lty = 2, col = "red") +
  geom_vline(xintercept = 1944.5, lty = 2, col = "blue") +
  geom_vline(xintercept = 1994.5, lty = 2, col = "brown") +
  annotate("text", x = c(1899,1921,1938,1966,1978,2006.5),
           y = c(9000,14000,19000,26000,30000,24000),
           label = c("End of deadball era",
                     "Stock market crash",
                     "D-Day",
                     "Minor League decline",
                     "Expansion era",
                     "Labor strike"),
           color = c("black","red","blue", "grey", "orange","brown")) +
  annotate("rect", fill = "grey", alpha = 0.2,
        xmin = 1949, xmax = 1960,
        ymin = -Inf, ymax = Inf) +
    annotate("rect", fill = "orange", alpha = 0.2,
        xmin = 1961, xmax = 1999,
        ymin = -Inf, ymax = Inf)

We now add our estimate of baseball interest. We will use interpolation for missing seasons. Smoothing will be applied. This smoothing helps with jaggedness and handles the jump in interest due to switching from Gallup to the average of Gallup and Harris. Historical interest in baseball is estimated and plotted below.

## Compute interest adjustment
#https://news.gallup.com/poll/4735/sports.aspx
#https://www.mprnews.org/story/2015/05/11/is-baseball-dying-no
favorite_Gallup = data.frame(
  year = c(1937, 1948, 1960, 1972, 1981, 1990, 1994, 1998, 2000, 2001, 2002,
           2003, 2004, 2005, 2006, 2007, 2008, 2013, 2014, 2017) + 10, 
  interest = c(0.34, 0.39, 0.34, 0.22, 0.16, 0.16, 0.18, 0.12, 0.13, 0.12, 0.12, 
               0.10, 0.10, 0.12, 0.11, 0.13, 0.10, 0.14, 0.14, 0.09)#/2 + 0.42/2
)
#Harris poll
#https://www.sportsbusinessjournal.com/Daily/Issues/2015/01/28/Research-and-Ratings/Harris-Poll.aspx
#https://www.businessinsider.com/most-popular-sports-in-the-us-2016-3
favorite_Harris = data.frame(year = c(1985, 1989, 1992, 1998, 2009, 2010, 
                                      2011, 2012, 2013, 2014, 2016) + 10, 
                             interest = c(0.23, 0.19, 0.21, 0.18, 0.16, 0.17, 
                                          0.13, 0.16, 0.14, 0.16, 0.15))
## Combined information
favorite = data.frame(
  year = 1947:2025,
  interest = approx(favorite_Gallup$year, favorite_Gallup$interest, xout = 1947:2025)$y
)
favorite[favorite$year >= 1995, ]$interest = 
  approx(favorite_Gallup$year, favorite_Gallup$interest, xout = 1995:2025)$y / 2 + 
  approx(favorite_Harris$year, favorite_Harris$interest, xout = 1995:2025)$y / 2
#https://news.gallup.com/poll/6745/baseball-fan-numbers-steady-decline-may-pending.aspx
#https://onlinemasters.ohio.edu/blog/mlb-young-fans/
#https://boxingjunkie.usatoday.com/2021/06/harris-poll-boxing-more-popular-than-mma-hockey-tennis-golf
interest = data.frame(
  year = c(1937,1952,2001,2021) + 10,
  interest = c(0.62,0.62,0.50,0.49)
)
# 50% for favorite; 50% for general interest
MLB_interest = data.frame(
  year = 1947:2025,
  interest = (approx(favorite$year, favorite$interest, xout = 1947:2025)$y +
                approx(interest$year, interest$interest, xout = 1947:2025,
                       rule = 2)$y)/2
)
# The existence of the MLB itself 
MLB_interest = rbind(c(1870,0.20), c(1876, 0.20), c(1886, 0.22), c(1920,0.30), 
                     c(1930, 0.38), MLB_interest)
dat_interest = data.frame(
  year = 1870:2025,
  interest = approx(MLB_interest$year, MLB_interest$interest, rule = 2, 
                    xout = 1870:2025)$y)
## interest from 1871-2025
interest = dat_interest$interest[-1]

We now plot smoothed interest in baseball over time.

dat_interest$interest_smooth = predict(lm(interest ~ ns(year, df=12), data=dat_interest))
ggplot(dat_interest, aes(x = year, y = interest)) +
  labs(title = "Estimated Interest in Baseball",
       subtitle = "as a proportion of total US population",
       y = "Proportion",
       x = "Year") +
  geom_line(aes(x = year, y = interest_smooth), lwd = 1) +
  theme_minimal() +
  ylim(c(0,0.60))

We now calculate the talent pool with the above interest adjustment applied.

## Get talent pool
region_perc_pop[155, ] = region_perc_pop[154, ]
region_perc_pop[155, 1] = 2025

dat_talent_pool = region_perc_pop %>% select(yearID, NEpMW_MLB, NEpMW_pop_prop) %>% 
  ## estimated population of aged 20-19 Males from MW and NE (white males times prop from MW and NE)
  mutate(white_eligible = race_demo$white[-1] * region_perc_pop$NEpMW_pop_prop) %>% 
  mutate(prop_white_MW_NE_MLB = prop_white_MW_NE_MLB$prop_white_MW_NE_MLB) %>%  
  mutate(interest = interest) %>% 
  #mutate(prop_white_NEpMW_MLB = NEpMW_MLB * prop_white_MW_NE_MLB) %>% 
  mutate(talent_pool = white_eligible / (prop_white_MW_NE_MLB) * interest) %>% 
  as.data.frame()

talent_pool = dat_talent_pool %>% 
  select(yearID, talent_pool) %>% 
  mutate(talent_pool = talent_pool * 1e6) %>% 
  rename(pop = talent_pool)

Back to topics.

Wars

Here we provide adjustments for World War I, World War II, and the Korean War. For WWI military service was minimal so we consider an interest level of 0.85 for the talent pool for years 1918 and 1919.

# WWI
talent_pool[talent_pool[, 1] %in% c(1918:1919), ]$pop = 
  talent_pool[talent_pool[, 1] %in% c(1918:1919), ]$pop * c(0.85,0.85)

This article states that roughly 100 MLB players served in the Korean War. We’ll use 0.85 as the interest level for both 1952 and 1953. We will also ignore a lingering talent drain due to the Korean War because military service was not nearly on Americans’ minds as it was in WWII.

# Korean WAR
talent_pool[talent_pool[, 1] %in% c(1952:1953), ]$pop = 
  talent_pool[talent_pool[, 1] %in% c(1952:1953), ]$pop * 
  c(0.85,0.85)

We make an extensive and detailed adjustment for WWII following Gary Bedingfield’s timeline. The steps we followed were to count the proportion of players who were active MLB players the year before they served. If a player did not have any post war stats and no credible case of returning to the MLB then they were removed from the MLB for one season. Players like Bobby Thomson who served in WWII but returned in their age 22 or younger season were not counted as MLB players who missed time due to WWII. This timeline says 7 and 18 MLB players served in WWII in 1941 and 1942, respectively.

Unfortunately, Gary Bedingfield’s timeline stops in 1942. Afterwards, Gary states that there were 195, 340, and 384 MLB players serving in WWII in, respectively, 1943, 1944, and 1945. However, his count seems to include people who played in the MLB and retired or those that would go on to play in the MLB in addition to active MLB players who left the league for service in WWII. So we will calculate the number of people who only played in the MLB from 1943-1946 as a proxy for the number of people serving in the MLB during the WWII years using the \(\texttt{People}\) data set in the \(\texttt{Lahman}\) package. This approach yielded 90, 166, and 170 MLB players serving in WWII in, respectively, 1943, 1944, and 1945. The roster size was set at 25 players in 1941-1944 (400 total spots) and 30 players in 1945 (480 total spots). We then incorporate a two-year lingering effect to the talent pool in which we use the 1943 interest level for 1946 and the 1942 interest level for 1947. This gives interest levels from 1941-1947: 0.983 0.96 0.78 0.59 0.65 0.78 0.96.

# WWII
talent_pool[talent_pool[, 1] %in% c(1941:1947), ]$pop = 
  talent_pool[talent_pool[, 1] %in% c(1941:1947), ]$pop * 
  (1- (c(7,18,90,166,170,90,18) / c(400,400,400,400,480,400,400)))
talent_pool$pop = round(talent_pool$pop)

Integration of NL and AL

Jackie Robinson broke the color barrier in the NL in 1947. Shortly after Larry Doby broke the color barrier in the AL. Our talent pool includes integration from 1951-1960. Armour (2007) showed that the pace of integration was different in the NL and AL, with the AL integrating at a slower pace. We now correct for this by an adjustment to the talent pool applied strictly to the AL. This adjustment will be:

\[ \text{AL integration adjustment} = \frac{\% \text{white win shares in NL}}{\% \text{white win shares in AL}}, \] where win shares is a metric developed by Bill James which allocates team wins to individual players (as stated in Armour (2007)), and percentage white win shares is the percentage of total win shares from the white players. The values for this adjustment are taken from Figures 5 and 7 in Armour (2007). We will assume that the leagues are both equally integrated when the gap in percentage white win shares closes in 1973.

## Figure 5 in Armour (2007)
foo = approx(x = c(1947, 1960, 1965, 1972, 1986), 
             y = c(1, 0.90, 0.80, 0.70, 0.70), 
             xout = 1947:1974)
## Figure 7 in Armour (2007)
bar = approx(x = c(1947, 1950, 1954, 1959, 1968, 1973, 1974), 
             y = c(0, 0.05, 0.05, 0.17, 0.16, 0.01, 0), 
             xout = 1947:1974)
integration_adjustment = data.frame(
  year = foo$x, adjustment = (foo$y - bar$y)/foo$y )

talent_pool$ALpop = round(talent_pool$pop)
talent_pool[talent_pool$year %in% 1947:1974, ]$ALpop = 
  round(talent_pool[talent_pool$year %in% 1947:1974, ]$ALpop * 
          integration_adjustment$adjustment)

Talent Pool

Below we report the final talent pool calculated in this analysis.

talent_pool = talent_pool %>% 
  rename(NLpop = pop, 
         year = yearID)
#write_csv(talent_pool, file = "talent-pool-v3.0.csv")

The plot below displays our estimate of the MLB talent pool. The ranges from 1957-1977 and 1999-2010 are highlighted. The MLB talent pool experienced rapid increases during those time periods. Subsequent plots examine reasons for this increase. A few plausible explanations arise:

talent_pool %>% 
  ggplot() + 
  aes(x = year, y = NLpop) +
  geom_line(aes(x = year, y = ALpop), col = "blue") +
  geom_line(col = "red") +   
  theme_minimal() + 
  labs(title = "Estimated Talent Pool Adjusted for Interest", 
       y = "Population", 
       x = "Year") + 
  annotate("rect", fill = "grey", alpha = 0.2, 
           xmin = 1957, xmax = 1977,
           ymin = -Inf, ymax = Inf) + 
  annotate("rect", fill = "grey", alpha = 0.2, 
           xmin = 1999, xmax = 2010,
           ymin = -Inf, ymax = Inf)

dat_talent_pool %>% 
  ggplot() + 
  aes(x = yearID, y = prop_white_MW_NE_MLB) +
  geom_line() + 
  theme_minimal() + 
  labs(title = "Proportion of MLB Players from MW and NE Regions and are White", 
       y = "Proportion", 
       x = "Year") + 
  ylim(0,1) + 
  annotate("rect", fill = "grey", alpha = 0.2, 
           xmin = 1957, xmax = 1977,
           ymin = -Inf, ymax = Inf) + 
    annotate("rect", fill = "grey", alpha = 0.2, 
           xmin = 1999, xmax = 2010,
           ymin = -Inf, ymax = Inf)

dat_talent_pool %>% 
  ggplot() + 
  aes(x = yearID, y = white_eligible) +
  geom_line() + 
  theme_minimal() + 
  labs(title = "White Eligible Population", 
       y = "Population", 
       x = "Year") + 
  ylim(0,8) +
  annotate("rect", fill = "grey", alpha = 0.2, 
           xmin = 1957, xmax = 1977,
           ymin = -Inf, ymax = Inf) + 
    annotate("rect", fill = "grey", alpha = 0.2, 
           xmin = 1999, xmax = 2010,
           ymin = -Inf, ymax = Inf)

dat_talent_pool %>% 
  ggplot() + 
  aes(x = yearID, y = interest) +
  geom_line() + 
  theme_minimal() + 
  labs(title = "Estimated Interest in Baseball", 
       y = "Population", 
       x = "Year") + 
  ylim(0,0.6) + 
  annotate("rect", fill = "grey", alpha = 0.2, 
           xmin = 1957, xmax = 1977,
           ymin = -Inf, ymax = Inf) + 
    annotate("rect", fill = "grey", alpha = 0.2, 
           xmin = 1999, xmax = 2010,
           ymin = -Inf, ymax = Inf)

region_perc_pop %>% 
  ggplot() + 
  aes(x = yearID, y = INTL) + 
  geom_line() + 
  theme_minimal() + 
  labs(title = "Proportion of MLB that is International", 
       x = "Year", 
       y = "Proportion") +
  ylim(0,0.40) + 
  annotate("rect", fill = "grey", alpha = 0.2, 
           xmin = 1957, xmax = 1977,
           ymin = -Inf, ymax = Inf) + 
    annotate("rect", fill = "grey", alpha = 0.2, 
           xmin = 1999, xmax = 2010,
           ymin = -Inf, ymax = Inf)

Back to topics.

Negro League Talent Pool

The Negro League talent pool is constructed by scaling the previously defined talent pool (1920–1948) by the maximum observed ratio of Black to white MLB players. This maximum occurs in 1975, which we treat as a benchmark for full integration in Major League Baseball.

We interpret this ratio as an upper bound on relative participation and use it as an “interest multiplier” for Black players in the pre-integration era. This adjustment accounts for the fact that raw demographic population shares alone do not accurately reflect the underlying distribution of baseball talent, given the exclusion of Black players from MLB prior to integration.

## get demographic proportions of MLB players from facial data
race_demo_MLB = faces %>% 
  filter(scope_class == "MLB") %>% 
  group_by(year) %>% 
  summarise(pred_A_A = mean(pred_race == "A-A"), 
            pred_white = mean(pred_race == "White")) %>% 
  mutate(prop_A_A = pred_A_A / pred_white)

## maximum proportion of Black to white
prop_A_A = max(race_demo_MLB$prop_A_A)

We now calculate the Negro League talent pool.

NL_talent_pool = data.frame(year = 1920:1948, 
                            pop = round(talent_pool %>% 
                              filter(year %in% 1920:1948) %>% 
                              pull(NLpop) * prop_A_A ))
#write_csv(NL_talent_pool, file = "Negro_League-talent-pool-v3.0.csv")

Back to topics.