Introduction

Midwesterners don’t think climate change is an issue facing them.

In surveys, most Midwestern states show lower-than-national-average rates of people who “believe global warming is happening” and are “worried about global warming.” Additionally, scores for the belief that “global warming will harm me personally” are much lower across the Midwest compared to other states.

It makes sense when you think about it: many Midwesterners don’t visibly face rising sea levels or increasing storm intensity. We don’t experience huge flooding events from hurricanes or massive wildfires like areas with large forests.

For Midwesterners, the main concern about climate change is increasing temperatures. We’re likely to have both hotter days than in previous years and more of those hot days overall.

There are obvious agricultural concerns impacting the Midwest, as corn and soybeans make up 75% of farmland. The corn market is projected to slow in yield growth, while soybean growth is projected to actually decrease.

This impacts people on a personal level as well. Exposure to heat increases the likelihood of heat stress—a condition where the body is unable to effectively regulate its temperature due to excessive environmental heat exposure.

Heat stress is the leading cause of weather-related deaths. Heat-related illnesses include heat cramps, heat exhaustion, heat rash, and heat stroke. Heat illnesses can exacerbate underlying conditions including cardiovascular disease, diabetes, mental health conditions, and asthma. It can also increase the risk of accidents and transmission of some infectious diseases.

Heat stress is likely to increase as temperatures and humidity continue to rise in this region, resulting in more heat-related deaths and illnesses.

In the United States, mortality increases 4% during heat waves compared with non-heat wave days. Heat-related mortality for people over 65 years of age also increased by approximately 85% between 2000–2004 and 2017–2021.

News Stories

It’s easy to envision the hypothetical impact of rising temperatures — yet we can already see the real effects in communities across the Midwest. In 2024, a few major heat waves of temperatures nearly at or above 100ºF.

During heat waves, emergency room visits often increase significantly; during one hot week in June 2024, Michigan saw a jump from 239 to 542 per 100,000 residents, surpassing the 95th percentile of typical rates, according to updated CDC heat health tracker data.

Heat waves are claiming lives. In July 2024, a 5 year old in Omaha, Nebraska died after being left in a hot car. In June, a 51 year old man died in a prison outside of Chicago where no windows or ventilation was provided on a day where temperatures hit over 90ºF.

Heat-related deaths are also dangerously undercounted. The CDC provides a dashboard for heat and health, including figures on heat related illnesses and deaths, but they acknowledge that these figures are likely severe underestimates. They have urged that extreme weather, including heat, be noted on death certificates, even when indirectly contributing to fatalities, but figures are still estimated to be much higher than the data shows.

The rise in heat waves is also evident in social media posts from local National Weather Service accounts. These posts aim to inform and prepare communities, offering a journalistic perspective on notifications and the history of heat waves impacting the Midwest.

Tweets from local NWS Twitter AccountsTweets from local NWS Twitter AccountsTweets from local NWS Twitter AccountsTweets from local NWS Twitter AccountsTweets from local NWS Twitter Accounts

Tweets from local NWS Twitter Accounts

Increasing Temperatures

In a dataset from the World Resources Institute, we can see the impact of various levels of warming on temperature projections for cities in the Midwest. This data examines a variety of climate hazards (defined as “a defined meteorological condition that without mitigation causes or exacerbates a negative societal impact”) on cities across the world. The Midwest cities included are Kansas City, Omaha, Minneapolis, Louisville, Chicago, Indianapolis, Milwaukee, Cincinnati, Columbus, Detroit, and Cleveland.

The models produce a variety of different warming scenarios and what they call ‘center point years’ that identify a year for when that level of warming will be achieved.

Center Point Years from WRI DataCenter Point Years from WRI Data

Center Point Years from WRI Data

Some models already have us as passing the first threshold (1.5ºC) and predict that we will pass the second threshold (2.0ºC) by 2024. The final threshold listed (3.0ºC) lists a variety of years, with a range of years between as soon as 2028 and as late as 2086 for other models.

35ºC Threshold

An important indicator to consider is the threshold of 35°C (95°F).

The metric Tmax35_days represents the annual count of days with maximum temperatures reaching or exceeding 35°C, or 95°F. This temperature threshold is widely regarded as a critical limit for human tolerance, as prolonged exposure to humid conditions at or above 35°C can be life-threatening.

By comparing different warming scenarios, we can evaluate the potential impacts on cities in the Midwest.

Recent Historical (1995 - 2014)

chart1_35_data <- climate_data %>%
  filter(hazard == "Tmax35_days", indicator == "expectedvalue")

chart1_35_data_hist <- chart1_35_data %>%
  filter(scenario == "Historical")
chart1_35_data_1 <- chart1_35_data %>%
  filter(scenario == "1.5C")
chart1_35_data_2<- chart1_35_data %>%
  filter(scenario == "2.0C")
chart1_35_data_3<- chart1_35_data%>%
  filter(scenario == "3.0C")

# Get state boundary data
states_map <- map_data("state")

# Define latitude and longitude bounds for the Midwest region
midwest_bounds <- list(
  xlim = c(-100, -80), # Longitude bounds
  ylim = c(35, 50)     # Latitude bounds
)


# Create the map visualization

ggplot() +
  # Add state boundaries
  geom_polygon(data = states_map, aes(x = long, y = lat, group = group), 
               fill = "gray80", color = "white", size = 0.2) +
  # Add city bubbles
  geom_point(data = chart1_35_data_hist, 
             aes(x = longitude, y = latitude, size = mean_estimate, 
                 fill = round(mean_estimate), 
                 color = round(mean_estimate)), # Match fill and color
             alpha = 0.6, shape = 21, stroke = 1) + # Stroke for outline thickness
  scale_size_continuous(
    name = "Days over 35ºC", 
    range = c(1, 17) # Increase bubble size range
  ) +
  scale_fill_distiller(
    name = "Rounded Days", 
    palette = "YlOrRd", # Use Brewer's yellow-to-red palette
    direction = 1 # Ensure colors go from yellow (low) to red (high)
  ) +
  scale_color_distiller(
    name = "Rounded Days", 
    palette = "YlOrRd", # Match Brewer's palette for outline
    direction = 1 # Ensure colors match fill
  ) +
  coord_fixed(xlim = midwest_bounds$xlim, ylim = midwest_bounds$ylim) + # Zoom to Midwest
  labs(
    title = "Days Over 35ºC Across Midwest Cities - Recent Historical",
    subtitle = "Bubble size and color represent days over 35ºC"
  ) +
  theme_minimal() +
  theme(
    strip.text = element_text(size = 12), # Customize facet labels
    legend.position = "right", # Position legends to the right
    axis.title = element_blank(), # Remove axis titles
    axis.text = element_blank(),  # Remove axis text
    axis.ticks = element_blank(), # Remove axis ticks
    panel.grid = element_blank()  # Remove gridlines
  )

1.5ºC Warming

# Create the map visualization
ggplot() +
  # Add state boundaries
  geom_polygon(data = states_map, aes(x = long, y = lat, group = group), 
               fill = "gray80", color = "white", size = 0.2) +
  # Add city bubbles
  geom_point(data = chart1_35_data_1, 
             aes(x = longitude, y = latitude, size = mean_estimate, 
                 fill = round(mean_estimate), 
                 color = round(mean_estimate)), # Match fill and color
             alpha = 0.6, shape = 21, stroke = 1) + # Stroke for outline thickness
  scale_size_continuous(
    name = "Days over 35ºC", 
    range = c(1, 17) # Increase bubble size range
  ) +
  scale_fill_distiller(
    name = "Rounded Days", 
    palette = "YlOrRd", # Use Brewer's yellow-to-red palette
    direction = 1 # Ensure colors go from yellow (low) to red (high)
  ) +
  scale_color_distiller(
    name = "Rounded Days", 
    palette = "YlOrRd", # Match Brewer's palette for outline
    direction = 1 # Ensure colors match fill
  ) +
  coord_fixed(xlim = midwest_bounds$xlim, ylim = midwest_bounds$ylim) + # Zoom to Midwest
  labs(
    title = "Days Over 35ºC Across Midwest Cities - 1.5ºC Warming",
    subtitle = "Bubble size and color represent days over 35ºC"
  ) +
  theme_minimal() +
  theme(
    strip.text = element_text(size = 12), # Customize facet labels
    legend.position = "right", # Position legends to the right
    axis.title = element_blank(), # Remove axis titles
    axis.text = element_blank(),  # Remove axis text
    axis.ticks = element_blank(), # Remove axis ticks
    panel.grid = element_blank()  # Remove gridlines
  )

2ºC Warming

# Create the map visualization
ggplot() +
  # Add state boundaries
  geom_polygon(data = states_map, aes(x = long, y = lat, group = group), 
               fill = "gray80", color = "white", size = 0.2) +
  # Add city bubbles
  geom_point(data = chart1_35_data_2, 
             aes(x = longitude, y = latitude, size = mean_estimate, 
                 fill = round(mean_estimate), 
                 color = round(mean_estimate)), # Match fill and color
             alpha = 0.6, shape = 21, stroke = 1) + # Stroke for outline thickness
  scale_size_continuous(
    name = "Days over 35ºC", 
    range = c(1, 17) # Increase bubble size range
  ) +
  scale_fill_distiller(
    name = "Rounded Days", 
    palette = "YlOrRd", # Use Brewer's yellow-to-red palette
    direction = 1 # Ensure colors go from yellow (low) to red (high)
  ) +
  scale_color_distiller(
    name = "Rounded Days", 
    palette = "YlOrRd", # Match Brewer's palette for outline
    direction = 1 # Ensure colors match fill
  ) +
  coord_fixed(xlim = midwest_bounds$xlim, ylim = midwest_bounds$ylim) + # Zoom to Midwest
  labs(
    title = "Days Over 35ºC Across Midwest Cities - 2.0ºC Warming",
    subtitle = "Bubble size and color represent days over 35ºC"
  ) +
  theme_minimal() +
  theme(
    strip.text = element_text(size = 12), # Customize facet labels
    legend.position = "right", # Position legends to the right
    axis.title = element_blank(), # Remove axis titles
    axis.text = element_blank(),  # Remove axis text
    axis.ticks = element_blank(), # Remove axis ticks
    panel.grid = element_blank()  # Remove gridlines
  )

3ºC Warming

# Create the map visualization
ggplot() +
  # Add state boundaries
  geom_polygon(data = states_map, aes(x = long, y = lat, group = group), 
               fill = "gray80", color = "white", size = 0.2) +
  # Add city bubbles
  geom_point(data = chart1_35_data_3, 
             aes(x = longitude, y = latitude, size = mean_estimate, 
                 fill = round(mean_estimate), 
                 color = round(mean_estimate)), # Match fill and color
             alpha = 0.6, shape = 21, stroke = 1) + # Stroke for outline thickness
  scale_size_continuous(
    name = "Days over 35ºC", 
    range = c(1, 17) # Increase bubble size range
  ) +
  scale_fill_distiller(
    name = "Rounded Days", 
    palette = "YlOrRd", # Use Brewer's yellow-to-red palette
    direction = 1 # Ensure colors go from yellow (low) to red (high)
  ) +
  scale_color_distiller(
    name = "Rounded Days", 
    palette = "YlOrRd", # Match Brewer's palette for outline
    direction = 1 # Ensure colors match fill
  ) +
  coord_fixed(xlim = midwest_bounds$xlim, ylim = midwest_bounds$ylim) + # Zoom to Midwest
  labs(
    title = "Days Over 35ºC Across Midwest Cities - 3.0ºC Warming",
    subtitle = "Bubble size and color represent days over 35ºC"
  ) +
  theme_minimal() +
  theme(
    strip.text = element_text(size = 12), # Customize facet labels
    legend.position = "right", # Position legends to the right
    axis.title = element_blank(), # Remove axis titles
    axis.text = element_blank(),  # Remove axis text
    axis.ticks = element_blank(), # Remove axis ticks
    panel.grid = element_blank()  # Remove gridlines
  )

Table

# Group by city and scenario, calculate average mean_estimate
average_temp_days <- chart1_35_data %>%
  group_by(city, scenario) %>%
  summarize(average_days = mean(mean_estimate, na.rm = TRUE), .groups = "drop")

# Pivot data to have scenarios as columns
pivoted_temp_days <- average_temp_days %>%
  pivot_wider(
    names_from = scenario,
    values_from = average_days
  )

# Calculate the increase relative to "recent historical"
pivoted_temp_days <- pivoted_temp_days %>%
  mutate(
    `1.5C Increase` = `1.5C` - `Historical`,
    `2.0C Increase` = `2.0C` - `Historical`,
    `3.0C Increase` = `3.0C` - `Historical`
  )

# Round data 
pivoted_temp_days <- pivoted_temp_days %>%
  mutate(across(where(is.numeric), ~ round(., 2)))


knitr::kable(
  pivoted_temp_days %>% 
    select(city, `Historical`, `1.5C Increase`, `2.0C Increase`, `3.0C Increase`)
)
city Historical 1.5C Increase 2.0C Increase 3.0C Increase
Chicago 6.67 -1.12 0.02 2.70
Cincinnati 4.10 -0.89 0.36 3.86
Cleveland 0.51 -0.17 0.28 0.88
Columbus 4.28 -0.90 0.25 0.59
Detroit 3.49 -0.21 0.72 1.43
Indianapolis 5.98 -1.15 0.11 1.06
Kansas City 15.47 1.83 7.41 4.87
Louisville 7.41 -2.46 -0.96 3.45
Milwaukee 4.58 0.35 1.29 0.71
Minneapolis 2.56 0.52 2.42 6.70
Omaha 13.57 0.35 -0.16 4.22

Most of the maps reveal at least one additional day exceeding 95°F under higher warming scenarios.

This trend is very clear in the 2.0°C and 3.0°C warming scenarios, with the most drastic effects observed in southern cities such as Kansas City, Omaha, Louisville, and Cincinnati.

Notably, Minneapolis stands out with a significant increase under extreme models, matching levels seen in cities like Chicago and Louisville, which are located much further south.

Clearly, these high temperatures are dangerous and likely to cause heatstroke or heat stress in people.

Different regions have varying levels of adaptation to hot weather. What insights can we gain by comparing the model’s output to local temperature norms?

Local Maximum Temperatures

Considering local temperature maximums is critical when examining climate change models, as communities are often adapted to their historical climate patterns. Infrastructure, public health systems, and daily life are built around these norms, meaning that even modest deviations from local temperature thresholds can have outsized impacts.

The indicator Tmax95pctl_days measures the annual number of days when the daily high temperature meets or exceeds the 95th percentile for a given location, based on a 40-year baseline (1980–2019). By focusing on locally defined extremes, this metric highlights the potential for disruption when temperatures exceed what residents and infrastructure are prepared to handle.

chart2_95_data <- climate_data %>%
  filter(hazard == "Tmax95pctl_days", indicator == "expectedvalue")

# Group by city and scenario, calculate average mean_estimate
average_95temp_days <- chart2_95_data %>%
  group_by(city, scenario) %>%
  summarize(average_95temp_days = mean(mean_estimate, na.rm = TRUE), .groups = "drop")

# Pivot data to have scenarios as columns
pivoted_95temp_days <- average_95temp_days %>%
  pivot_wider(
    names_from = scenario,
    values_from = average_95temp_days
  )

# Calculate the increase relative to "recent historical"
pivoted_95temp_days <- pivoted_95temp_days %>%
  mutate(
    `1.5C Increase` = `1.5C` - `Historical`,
    `2.0C Increase` = `2.0C` - `Historical`,
    `3.0C Increase` = `3.0C` - `Historical`
  )

# Round data 
pivoted_95temp_days <- pivoted_95temp_days %>%
  mutate(across(where(is.numeric), ~ round(., 2)))


knitr::kable(
  pivoted_95temp_days %>% 
    select(city, `Historical`, `1.5C Increase`, `2.0C Increase`, `3.0C Increase`)
)
city Historical 1.5C Increase 2.0C Increase 3.0C Increase
Chicago 50.80 2.61 7.33 14.21
Cincinnati 44.92 -1.78 0.64 18.70
Cleveland 43.58 0.21 2.16 14.08
Columbus 47.87 -0.12 1.28 15.03
Detroit 46.85 1.48 2.91 11.51
Indianapolis 51.31 -2.38 4.37 12.18
Kansas City 42.34 4.16 13.04 13.01
Louisville 43.66 -1.20 0.92 13.49
Milwaukee 47.34 2.66 3.24 16.03
Minneapolis 41.97 4.83 9.75 22.26
Omaha 47.81 1.79 2.93 9.25

This table highlights the significant increases in the number of extreme heat days per city, with some locations experiencing nearly two additional weeks of days exceeding the local 95th percentile at the most extreme warming scenarios.

bubble_data <- pivoted_95temp_days %>%
  left_join(chart2_95_data %>% select(city, latitude, longitude) %>% distinct(), by = "city") %>%
  pivot_longer(
    cols = c("1.5C Increase", "2.0C Increase", "3.0C Increase"),
    names_to = "scenario",
    values_to = "increase"
  )


# Create the faceted map
ggplot() +
  # Add state boundaries
  geom_polygon(data = states_map, aes(x = long, y = lat, group = group), 
               fill = "gray85", color = "white", size = 0.2) +
  # Add city bubbles sized by the increase in days
  geom_point(data = bubble_data, 
             aes(x = longitude, y = latitude, size = increase, 
                 fill = round(increase), 
                 color = round(increase)), # Match fill and color
             alpha = 0.7, shape = 21, stroke = 0.8) + # Adjust transparency and outline
  scale_size_continuous(
    name = "Increase in Days", 
    range = c(0, 12) # Adjust bubble size for better differentiation
  ) +
  scale_fill_distiller(
    name = "Increase", 
    palette = "YlOrRd", 
    direction = 1
  ) +
  scale_color_distiller(
    name = "Increase", 
    palette = "YlOrRd", 
    direction = 1
  ) +
  coord_fixed(xlim = midwest_bounds$xlim, ylim = midwest_bounds$ylim) + # Midwest focus
  labs(
    title = "Increase in Days Over 95th Percentile Across Midwest Cities",
    subtitle = "Bubble size and color represent the increase in days under warming scenarios"
  ) +
   facet_wrap(~ scenario, nrow = 1) + # Arrange facets horizontally
  theme_minimal() +
  theme(
    strip.text = element_text(size = 12, face = "bold"), # Enhance facet labels
    legend.position = "right", 
    axis.title = element_blank(), 
    axis.text = element_blank(),  
    axis.ticks = element_blank(), 
    panel.grid = element_blank()  
  )

Different cities are expected to experience different levels of heat, with southern cities seeing the biggest jumps. Even northern cities are seeing notable changes, especially with more extreme warming. Once again, we note that Minneapolis faces significant temperature increases in the most extreme warming scenarios. Furthermore, all cities across the Midwest are likely to experience much warmer periods than they do currently.

But what does this look like to the average person? Does this translate into a concrete impact on everyday lives?

If we were to draw this out on a calendar, an increase of up to two weeks of much warmer temperature appears pretty extreme.

Here we take weather data from Chicago in 2024 where temperatures were at or above the 95th percentile for heat (about 87ºF) and place it on a calendar. Below is what summers could look like at the estimated rate of warming.

Days above 95th Percentile, 2024

Days above 95th Percentile, Potential 2029

If warming continues at the predicted rates, some months could see nearly more days above 87º than not.

Increasing Heatwaves

It is also crucial to consider heatwaves in addition to overall warmer temperatures when assessing climate change impacts. Heatwaves—defined as periods of abnormally hot weather—are typically marked by three or more consecutive days where the daily high temperature meets or exceeds the local 90th percentile for daily maximum temperatures. This metric measures the frequency of heatwaves, calculated as the number of distinct heatwaves per year.

Heatwaves are becoming more frequent, further amplifying the risks associated with extreme heat. While general temperature increases are concerning, heatwaves present additional challenges, as extended periods of high temperatures can strain public health systems, infrastructure, and energy resources. These extended heat events can be particularly hazardous, especially for vulnerable populations and regions unprepared for such prolonged extreme conditions.

# FIND THE AVERAGE NUMBER OF HEATWAVES PER WARMING SCENARIO
heatwave_count <- climate_data %>%
  filter(hazard == "heatwave_count",
         indicator == "expectedvalue")

average_heatwave_count <- heatwave_count %>%
  group_by(scenario) %>%
  summarize(avg_heatwave_count = mean(mean_estimate, na.rm = TRUE), .groups = "drop") 

ggplot(average_heatwave_count, aes(x = scenario, y = avg_heatwave_count, color = scenario)) +
  geom_point(size = 4) +                     # Add points
  scale_y_continuous(limits = c(5, 9)) + 
  geom_text(aes(label = round(avg_heatwave_count, 2)), # Add labels with rounded values
            vjust = -1, size = 4) +          # Position labels above points
  theme_minimal() +                          # Minimal theme for clean aesthetics
  labs(
    title = "Average Heatwave Count by Warming Scenario",
    x = "Scenario",
    y = "Average Heatwave Count",
    color = "Scenario"
  ) +
  theme(
    legend.position = "none"
  ) +
  scale_color_manual(values = c("#FEB24CFF", "#FD8D3CFF", "#E31A1CFF", "#800026FF"))

This shows that Midwestern cities can expect an increase in the frequency of heatwaves, with the average number of heatwaves per year rising from 6.4 in the Recent Historical scenario to 7.5 in the worst case 3.0C scenario. While this might seem like only one additional heatwave per year, it’s important to consider the cumulative toll these events can have. Even a single heatwave can have severe consequences, including heat-related illnesses, strain on healthcare systems, power grids, and overall community resilience.

Models

heatwave_count$scenario <- factor(heatwave_count$scenario, levels = rev(levels(factor(heatwave_count$scenario))))

ggplot(heatwave_count, aes(x = mean_estimate, y = scenario, color = model)) +
  geom_point(size = 4, alpha = 0.8) +  
  scale_x_continuous(limits = c(3, 10)) + 
  facet_wrap(~ city, ncol = 2, scales = "free_y") +  # Split into 2 columns
  theme_minimal() +
  theme(
    strip.text = element_text(size = 10),  # Adjust facet label size
    legend.position = "bottom",           # Move legend to the bottom
    legend.title = element_text(size = 12),
    legend.text = element_text(size = 10),
    axis.title.y = element_blank()        # Remove y-axis label
  ) +
  labs(
    title = "Heatwave Count by Model and Scenario",
    color = "Model", 
    x = "Yearly Heatwave Count",
  ) +
    scale_color_manual(values = c("#FED976FF", "#FEB24CFF", "#FD8D3CFF", "#FC4E2AFF", "#E31A1CFF", "#BD0026FF", "#800026FF"))

Table

# FIND THE AVERAGE NUMBER OF HEATWAVES PER WARMING SCENARIO PER CITY
average_heatwave_city <- heatwave_count %>%
  group_by(city,scenario) %>%
  summarize(average_heatwave_city = mean(mean_estimate, na.rm = TRUE), .groups = "drop")

average_heatwave_city <- average_heatwave_city %>%
  pivot_wider(
    names_from = scenario, 
    values_from = average_heatwave_city
  )%>%
  mutate(across(where(is.numeric), ~ round(., 1)))

knitr::kable(average_heatwave_city)
city 3.0C 2.0C 1.5C Historical
Chicago 7.8 8.0 7.0 6.9
Cincinnati 8.0 6.6 5.7 6.3
Cleveland 7.6 6.5 6.2 6.5
Columbus 7.9 6.4 6.4 6.8
Detroit 7.7 7.3 6.8 6.7
Indianapolis 7.3 7.2 6.9 7.2
Kansas City 6.7 6.7 5.9 5.1
Louisville 7.4 6.0 5.9 6.5
Milwaukee 7.1 6.3 6.3 6.3
Minneapolis 7.5 7.0 6.6 6.2
Omaha 7.5 7.0 6.7 6.3

Cities across the Midwest are projected to experience varying shifts in heatwave frequency. For example, Chicago may see a slight increase, from 6.9 in the Recent Historical scenario to 7.8 in the 3.0C scenario, while cities like Cincinnati and Louisville are projected to see larger increases, with Cincinnati moving from 6.3 to 8.0 and Louisville from 6.5 to 7.4. Even small shifts in heatwave frequency can significantly affect public health, particularly for elderly, low-income, and other vulnerable groups who may struggle to cope with extended periods of extreme heat. This emphasizes the need for proactive heatwave preparedness and climate adaptation strategies.

Heatwave Duration

Not only will there be more heatwaves, but they are also likely to be longer. The length of heatwaves is a critical factor to consider, as prolonged periods of extreme heat can have even greater impacts on public health, infrastructure, and the environment.

This hazard is calculated as the length in days of the longest heatwave in a year, with a heatwave defined as three or more consecutive days where the daily high temperature meets or exceeds the local 90th percentile for daily maximum temperatures. As temperatures continue to rise, the duration of heatwaves is expected to increase, meaning that communities may face extended periods of extreme heat, which can overwhelm cooling systems, increase the risk of heat-related illnesses, and put additional strain on energy resources.

Model

heatwave_duration <- climate_data %>%
  filter(hazard == "heatwave_duration",
         indicator == "expectedvalue")

heatwave_duration$scenario <- factor(heatwave_duration$scenario, levels = rev(levels(factor(heatwave_duration$scenario))))

ggplot(heatwave_duration, aes(x = mean_estimate, y = scenario, color = model)) +
  geom_point(size = 4, alpha = 0.8) +  
  scale_x_continuous(limits = c(0, 24)) + 
  facet_wrap(~ city, ncol = 2, scales = "free_y") +  # Split into 2 columns
  theme_minimal() +
  theme(
    strip.text = element_text(size = 10),  # Adjust facet label size
    legend.position = "bottom",           # Move legend to the bottom
    legend.title = element_text(size = 12),
    legend.text = element_text(size = 10),
    axis.title.y = element_blank()        # Remove y-axis label
  ) +
  labs(
    title = "Heatwave Duration by Model and Scenario",
    x = "Longest Heatwave Duration",
    color = "Model"
  )  +
    scale_color_manual(values = c("#FED976FF", "#FEB24CFF", "#FD8D3CFF", "#FC4E2AFF", "#E31A1CFF", "#BD0026FF", "#800026FF"))

Table

# FIND AVERAGE LENGTH OF LONGEST HEATWAVE PER CITY PER SCENARIO
average_duration_city <- heatwave_duration %>%
  group_by(city,scenario) %>%
  summarize(average_heatwave_duration = mean(mean_estimate, na.rm = TRUE), .groups = "drop") 

average_duration_city <- average_duration_city %>%
  pivot_wider(
    names_from = scenario, 
    values_from = average_heatwave_duration
  )%>%
  mutate(across(where(is.numeric), ~ round(., 1)))

knitr::kable(
  average_duration_city %>% 
    select(city, `Historical`, `1.5C`, `2.0C`, `3.0C`)
)
city Historical 1.5C 2.0C 3.0C
Chicago 13.0 12.8 13.0 19.6
Cincinnati 10.9 9.9 11.2 15.8
Cleveland 9.3 10.5 10.1 14.8
Columbus 10.3 11.0 12.7 15.4
Detroit 10.6 11.7 11.4 15.6
Indianapolis 11.9 11.7 12.8 18.1
Kansas City 13.8 14.8 15.3 18.0
Louisville 11.9 10.4 9.4 13.1
Milwaukee 11.5 12.1 12.5 18.9
Minneapolis 10.7 11.7 14.3 19.1
Omaha 14.7 13.9 13.3 14.8

This shows the average duration (in days) of the longest heatwave per year under different warming scenarios, highlighting that with higher warming, heatwaves not only become more frequent but also last longer, increasing risks to public health and infrastructure. Most models suggest that the longest heatwaves in the Recent Historical period last between 8 and 15 days across Midwest cities, though some cities are already seeing heatwaves that last up to or over three weeks. When looking at the shift from the Recent Historical period to the 1.5C, 2.0C, and 3.0C scenarios, it’s clear that all cities are expected to experience longer heatwaves, with some cities facing significant increases in duration.

  • Chicago, in the 3.0C scenario, the average duration will increase by 6.6 days, reaching 19.6 days. This marks a significant extension of the longest heatwave each year.

  • Kansas City experiences the longest heatwaves in the historical scenario (13.8 days), which rise significantly to 18.0 days by the 3.0C scenario, marking a jump of about 4.2 days.

  • Milwaukee will experience a considerable jump in heatwave length from 11.5 days in the Recent Historical scenario to 18.9 days under the 3.0C scenario, adding over 7 days to the longest heatwave of the year.

  • Minneapolis, traditionally a cooler city, will see an increase in heatwave duration from 10.7 days to 19.1 days, a striking rise of nearly 9 days, especially given its northern location.

Human Impact

The human costs of climate change are expected to be profound and wide-reaching, impacting individuals on multiple fronts.

As heatwaves become more frequent and intense, people will experience increased health risks, including heat exhaustion, heatstroke, and cardiovascular problems, particularly among vulnerable groups like the elderly, children, and those with pre-existing conditions. The strain on healthcare systems will grow, as more individuals seek treatment for heat-related illnesses.

Additionally, extreme heat will affect labor productivity, especially in outdoor and agricultural work, leading to economic losses. Beyond physical health, the mental toll of prolonged heat and environmental stress may increase, exacerbating anxiety and social disparities.

People will also face disruptions to daily life through higher energy costs, reduced water availability, and damage to infrastructure, making it harder for communities to adapt and thrive.

Ultimately, the impacts of climate change will make everyday life more challenging, particularly for those who are already marginalized or economically vulnerable.

What can we do? Continue here to read about what mitigation and adaptation strategies Midwestern cities have already started.