Data and R code to reproduce the analysis underlying this Jul. 6, 2025 Inside Climate News article, examining problems in the Florida home insurance market in the face of climate change.
# load required packages
library(tidyverse)
library(tidycensus)
library(readxl)
library(janitor)
In December 2024, the U.S. Senate Committee on the Budget released data from a survey and report concluding that severe weather events influenced by climate change have driven rising insurance non-renewals across the nation.
# load and process data
file_path <- "data/senate.xlsx"
sheet_names <- excel_sheets(file_path)
non_renewal <- map_dfr(sheet_names, ~ {
read_excel(file_path, sheet = .x) %>%
mutate(sheet_name = .x) %>%
bind_rows() %>%
clean_names()
})
non_renewal <- non_renewal %>%
mutate(year = as.integer(word(sheet_name)),
state = case_when(nchar(county) == 2 ~ county)) %>%
fill(state, .direction = "down") %>%
select(-sheet_name) %>%
rename(calculated_policies_in_force = calculated_policies_in_force_b_c) %>%
filter(!grepl("/", county))
counties_few_policies <- non_renewal %>%
filter(year == 2022 & calculated_policies_in_force < 250) %>%
select(state,county) %>%
mutate(flag = "<250 policies in 2022")
fl_non_renewal <- non_renewal %>%
filter(nchar(county) > 2 & county != "Grand Total" & state == "FL") %>%
select(state,county,year,non_renewal_pc = calculated_non_renewal_rate) %>%
mutate(non_renewal_pc = non_renewal_pc * 100)
fl_non_renewal_wide <- fl_non_renewal %>%
pivot_wider(names_from = year, values_from = non_renewal_pc, names_prefix = "nonrenewal_") %>%
clean_names() %>%
mutate(pc_change_non_renewal = (nonrenewal_2023 - nonrenewal_2018)/nonrenewal_2018 *100) %>%
left_join(counties_few_policies)
To provide socioeconomic context, we added data on county-level median household income from the U.S. Census Bureau’s 2019-2023 5-year American Community Survey.
income <- get_acs(geography = "county",
state = "FL",
variables = c(median_income = "B19013_001"),
output = "wide",
year = 2023) %>%
clean_names() %>%
separate(name, into = c("county", "state"), sep = ", ") %>%
mutate(county = gsub(" County", "", county),
county = str_to_upper(county),
state = state.abb[match(state, state.name)]) %>%
arrange(state,county)
To consider risks from natural hazards and measures of social vulnerability and resilience, we used data from the Federal Emergency Management Agency’s National Risk Index (NRI).
nri <- read_csv("data/NRI_Table_Counties/NRI_Table_Counties.csv") %>%
clean_names() %>%
select(stcofips,population,alr_valb,alr_vra_npctl)
fl_combined <- left_join(income,fl_non_renewal_wide, by = c("state","county")) %>%
left_join(nri, by = c("geoid" = "stcofips")) %>%
left_join(fl_premiums_wide %>% select(-county), by = "geoid") %>%
mutate(county = str_to_title(county),
county = str_replace(county, "Desoto","DeSoto"))
write_csv(fl_combined, "processed_data/fl_combined.csv")
Hover over any county to see the non-renewal rate from the Senate Budget Committee report and median household income. The maps show that four counties around Lake Okeechobee—Glades, Hendry, Highlands and Okeechobee—are an epicenter of the state’s insurance non-renewal crisis.
The expected annual loss rate for buildings is a measure from the NRI that provides a way to compare the risk to buildings from all natural hazards, irrespective of the value of the properties involved. A value of 0.005, for instance, means that for every ten dollars of building value across a county, you would expect losses of five cents in a given year. Viewed in this way, the risk to buildings for the counties around Lake Okeechobee is not especially high compared to other Florida counties.
The social vulnerability and community resilience adjusted expected annual loss rate is a measure from the NRI that extends the assessment of expected annual losses to buildings, crops and people to take account of socioeconomic factors that affect vulnerability and resilience in the face of natural hazards. It is expressed here as a national percentile, meaning that a county with a score of more than 95 is in the riskiest 5 percent of counties across the nation.
Household income is an important determinant of social vulnerability and community resilience. The counties around Lake Okeechobee are among the poorest in Florida.
In the face of rising climate-related hazards, the crisis of home insurance non-renewal has hit hardest in low-income counties in Florida with low community resilience and high social vulnerability.
citizens <- read_csv("data/citizens_policies_counties.csv") %>%
mutate(county = str_replace(county, "Saint","St.")) %>%
pivot_wider(names_from = "county", values_from = "policies") %>%
filter(date >= "2018-01-01")
write_csv(citizens, "processed_data/citizens.csv", na = "")
The Citizens Property Insurance Corp. is Florida’s state-backed insurer of last resort. This chart shows how, across the state, the number of policies held by Citizens grew dramatically over the period covered by the Senate Budget Committee report, especially in wealthy coastal counties including Broward and Miami-Dade. This started before the crisis of non-renewal documented in this committee’s report, probably reflecting rising premiums from other insurance companies and a loss of coverage from smaller companies facing financial difficultes. Citizens is now reducing the number of policies it holds by offering financial incentives for companies to take them over in a process it calls “depopulation.”