Combined Half No-Hitters

PUBLISHED ON DEC 23, 2020

In August 2020 on Episode 1580 of “Effectively Wild”, there was a discussion about “Combined Half No-Hitters”, where neither team allows a hit through 4.5 innings, leading to 9 total half-innings without a hit. I did the queries in my Retrosheet database to find a list of every combined half no-hitter.

To look this up, I first read in attached my R session to my PostgreSQL database using the “dbcon.R” file, then read in the necessary columns of the play-by-play table.

library(tidyverse)
library(lubridate)
source("dbcon.R")
pbp <- dbGetQuery(con, "select game_id, away_team_id, inn_ct, bat_home_id, event_cd from retro_pbp_2")
games <- dbGetQuery(con, "select game_id, home_starting_pitcher_name, visitor_starting_pitcher_name from retro_games")

I then filter the play-by-play to the first 4.5 innings of the games, grouped by the game, and counted the number of hits (hits have an event code between 20 and 23). Games that fit the combined half no-hitter description will have no hits in the first 4.5 innings, so I filter to the games that have no hits and arrange by most recent date. The below table shows every combined half no-hitter in the database.

nohit <- pbp %>% 
  filter(inn_ct < 5 | (inn_ct == 5 & bat_home_id == 0)) %>% 
  group_by(game_id, away_team_id) %>% 
  summarize(n_hits = sum(event_cd %in% 20:23, na.rm = TRUE)) %>% 
  ungroup() %>% 
  filter(n_hits == 0) %>% 
  arrange(desc(as.numeric(substr(game_id, 4,11))))

nohit %>% 
  mutate(home_team = substr(game_id, 1,3)) %>% 
  mutate(date = ymd(as.numeric(substr(game_id, 4,11)))) %>% 
  left_join(games, by = "game_id") %>% 
  select(Date = date,
         "Home Team" = home_team, 
         "Home Starter" = home_starting_pitcher_name,
         "Away Team" = away_team_id,
         "Away Starter" = visitor_starting_pitcher_name) %>%
  kableExtra::kable() %>% 
  kableExtra::kable_styling() %>% 
  kableExtra::scroll_box(height = "500px")
Date Home Team Home Starter Away Team Away Starter
2020-09-20 SEA Justin Dunn SDN Dinelson Lamet
2020-09-10 OAK Sean Manaea HOU Jose Urquidy
2020-08-18 MIN Kenta Maeda MIL Corbin Burnes
2019-04-04 NYN Noah Syndergaard WAS Stephen Strasburg
2019-03-28 TOR Marcus Stroman DET Jordan Zimmermann
2018-08-22 TOR Thomas Pannone BAL David Hess
2018-08-03 OAK Brett Anderson DET Blaine Hardy
2018-05-06 NYA Domingo German CLE Mike Clevinger
2017-08-20 DET Justin Verlander LAN Kenta Maeda
2016-05-30 ANA Jhoulys Chacin DET Justin Verlander
2015-07-29 TBA Chris Archer DET Justin Verlander
2015-06-24 TBA Nathan Karns TOR Marco Estrada
2014-08-02 NYN Jacob deGrom SFN Jake Peavy
2014-04-17 CHA Chris Sale BOS Jon Lester
2014-04-02 MIL Matt Garza ATL Aaron Harang
2012-04-07 CLE Ubaldo Jimenez TOR Brandon Morrow
2011-06-24 PHI Vance Worley OAK Guillermo Moscoso
2011-04-24 FLO Josh Johnson COL Ubaldo Jimenez
2011-04-13 PIT Kevin Correia MIL Shaun Marcum
2010-10-01 CIN Travis Wood MIL Mark Rogers
2010-08-01 CHA Gavin Floyd OAK Gio Gonzalez
2010-07-26 TBA Matt Garza DET Max Scherzer
2010-06-13 CHN Ted Lilly CHA Gavin Floyd
2009-05-25 MIL Yovani Gallardo SLN Chris Carpenter
2008-07-09 LAN Derek Lowe ATL Tim Hudson
2007-08-21 DET Jair Jurrjens CLE Fausto Carmona
2007-05-13 TOR Shaun Marcum TBA Jae Weong Seo
2006-09-25 TOR Shaun Marcum BOS Tim Wakefield
2006-05-08 TOR Roy Halladay ANA Jeff Weaver
2006-05-07 TOR Casey Janssen ANA John Lackey
2003-06-18 NYA Roger Clemens TBA Victor Zambrano
2002-08-22 BAL John Stephens TBA Jorge Sosa
2001-08-04 HOU Roy Oswalt MON Tomo Ohka
2000-07-29 MIN Eric Milton NYA Roger Clemens
1997-07-27 TOR Pat Hentgen KCA Jose Rosado
1997-06-10 SFN William VanLandingham FLO Kevin Brown
1996-05-01 NYN Mark Clark MON Pedro Martinez
1994-07-28 SDN Bill Krueger CIN Erik Hanson
1994-04-09 NYA Jimmy Key DET Mike Moore
1993-05-22 KCA Kevin Appier SEA Jim Converse
1992-05-12 HOU Jimmy Jones CHN Mike Morgan
1991-07-28 LAN Mike Morgan MON Dennis Martinez
1991-06-18 DET Frank Tanana OAK Bob Welch
1991-06-12 OAK Mike Moore DET Frank Tanana
1990-07-01 CHA Greg Hibbard NYA Andy Hawkins
1988-09-16 CIN Tom Browning LAN Tim Belcher
1987-09-27 OAK Rick Honeycutt CHA Dave LaPoint
1986-06-27 OAK Chris Codiroli CHA Neil Allen
1986-06-24 DET Eric King BAL Scott McGregor
1986-06-17 MIL Danny Darwin TOR Jimmy Key
1984-05-20 PIT Jose DeLeon ATL Len Barker
1983-08-19 LAN Alejandro Pena PHI Steve Carlton
1983-05-27 SDN Eric Show NYN Tom Seaver
1980-07-13 CHA Steve Trout NYA Rudy May
1980-04-30 TOR Jesse Jefferson KCA Larry Gura
1979-09-03 HOU Joe Niekro LAN Jerry Reuss
1979-04-07 CLE Rick Waits BOS Mike Torrez
1978-07-23 LAN Don Sutton SLN Pete Vuckovich
1978-06-16 CIN Tom Seaver SLN John Denny
1977-06-09 CHN Bill Bonham SFN Ed Halicki
1977-06-08 CAL Nolan Ryan TOR Jesse Jefferson
1976-06-23 HOU J.R. Richard LAN Rick Rhoden
1976-06-07 PIT Bruce Kison CIN Jack Billingham
1974-07-13 CHA Wilbur Wood BAL Mike Cuellar
1973-09-26 OAK Catfish Hunter MIN Bert Blyleven
1973-08-19 CHN Rick Reuschel LAN Tommy John
1973-08-03 CAL Bill Singer OAK Vida Blue
1973-06-12 HOU Ken Forsch CHN Rick Reuschel
1972-07-27 CHA Stan Bahnsen KCA Roger Nelson
1971-09-22 BOS Mike Garman DET Mickey Lolich
1971-04-13 CHA Tom Bradley CAL Andy Messersmith
1968-05-07 ATL Dick Kelley PIT Al McBean
1967-08-16 WS2 Camilo Pascual CLE Steve Hargan
1965-09-19 PIT Bob Veale PHI Chris Short
1965-09-09 LAN Sandy Koufax CHN Bob Hendley
1965-07-09 CAL George Brunet CLE Ralph Terry
1964-09-11 MLN Denny Lemaster CIN Jim Maloney
1963-09-05 SFN Bobby Bolin HOU Don Nottebart
1963-08-10 LAA Dean Chance NYA Whitey Ford
1963-07-16 CHN Bob Buhl MLN Bob Sadowski
1959-07-17 NYA Ralph Terry CHA Early Wynn
1959-06-18 CHN Moe Drabowsky PIT Ron Kline
1959-04-10 PHI Robin Roberts CIN Don Newcombe
1956-07-04 DET Paul Foytack CLE Herb Score
1955-09-07 NYA Whitey Ford KC1 Arnie Portocarrero
1955-06-01 KC1 Ray Herbert NYA Johnny Kucks
1954-06-09 WS1 Bob Porterfield CLE Mike Garcia
1953-07-10 CHA Billy Pierce CLE Bob Feller
1952-05-15 DET Virgil Trucks WS1 Bob Porterfield
1951-07-12 CLE Bob Feller NYA Allie Reynolds
1947-06-22 CIN Ewell Blackwell BRO Joe Hatten
1944-09-16 BSN Red Barrett BRO Chink Zachary
1944-08-06 PHA Jesse Flores NYA Monk Dubiel
1944-05-17 PHA Bobo Newsom DET Dizzy Trout
1942-04-19 CHN Claude Passeau CIN Paul Derringer
1941-09-13 SLN Mort Cooper BRO Whit Wyatt
1939-07-08 NYA Marius Russo BOS Denny Galehouse
1936-09-01 PHA Red Bullock DET Schoolboy Rowe
1934-05-28 NY1 Hal Schumacher PIT Larry French
1933-07-20 WS1 General Crowder DET Tommy Bridges
1931-09-21 BOS Ed Morris SLA Sam Gray
1927-09-17 PHA Eddie Rommel SLA Sad Sam Jones
1927-08-11 SLN Pete Alexander PIT Vic Aldridge
1926-09-06 CIN Jakie May CHN Charlie Root
1925-08-15 NY1 Virgil Barnes BRO Dazzy Vance
1924-04-15 BOS Howard Ehmke NYA Bob Shawkey
1919-08-10 WS1 Jim Shaw CHA Eddie Cicotte
1918-06-05 CLE Johnny Enzmann BOS Bullet Joe Bush
1918-05-11 PHA Scott Perry CHA Frank Shellenback
1916-07-20 WS1 Harry Harper CHA Reb Russell
1916-04-23 CHN George McConnell PIT Erv Kantlehner

There are 111 combined half no-hitters in the database, which is about half the number of true no-hitters. The below chart shows the number of no-hitters of each type for each season going back to 1970.

nohit_real <- pbp %>% 
  group_by(game_id, away_team_id, bat_home_id) %>% 
  filter(max(inn_ct) >= 8) %>% 
  summarize(n_hits = sum(event_cd %in% 20:23, na.rm = TRUE)) %>% 
  ungroup() %>% 
  filter(n_hits == 0) %>% 
  arrange(desc(as.numeric(substr(game_id, 4,11))))

ggplot() +
  geom_line(nohit %>% ungroup() %>% count(year = as.numeric(substr(game_id,4,7))) %>% complete(year = 1916:2020, fill = list(n=0)), mapping = aes(x=year, y = n, col = "4.5 Inning"), na.rm = TRUE) +
  geom_point(nohit %>% ungroup() %>% count(year = as.numeric(substr(game_id,4,7))) %>% complete(year = 1916:2020, fill = list(n=0)), mapping = aes(x=year, y = n, col = "4.5 Inning"), na.rm = TRUE) +
  geom_line(nohit_real %>% ungroup() %>% count(year = as.numeric(substr(game_id,4,7))) %>% complete(year = 1916:2020, fill = list(n=0)), mapping = aes(x=year, y = n, col = "Regular"), na.rm = TRUE) +
  geom_point(nohit_real %>% ungroup() %>% count(year = as.numeric(substr(game_id,4,7))) %>% complete(year = 1916:2020, fill = list(n=0)), mapping = aes(x=year, y = n, col = "Regular"), na.rm = TRUE) +
  theme_light() +
  xlim(c(1970,2020)) +
  labs(x= "Year", y = "Number of Games",
       col = "No-Hitter Type")

In the episode, Ben Lindbergh and Sam Miller talked about why there are about half as many of these combined half no-hitters as there are regular no-hitters. My theory is that in each game, there are two opportunities for a regular no-hitter (one for the home team, one for the away team), but only one opportunity for a combined half no-hitter.