This report analyzes the U.S. National Oceanic and Atmospheric
Administration (NOAA) Storm Database for the year 2025 to identify
patterns in severe weather events and their consequences for public
health and the economy. The dataset was assembled by joining three CSV
files — event details, fatalities, and locations — using the shared
EVENT_ID key. The analysis reveals that tornadoes,
thunderstorm winds, and flash floods are the most frequent event types
and among the most harmful to human health in terms of fatalities and
injuries. Certain states, particularly those in the central and
southeastern United States, experience disproportionately high storm
activity. Monthly distribution of events shows a strong seasonal
pattern, with storm activity peaking in the spring and summer months. A
supplementary analysis examines the economic cost of weather events by
state, revealing that property and crop damage is concentrated in a
small number of high-impact event types. This report is intended to
inform government and municipal managers responsible for emergency
preparedness and resource allocation decisions.
The data are sourced from NOAA’s Storm Events database. Three CSV files for the year 2025 are used:
folder_path <- "/Users/tylerderkovitz/Downloads/storm_data"
details_file <- file.path(folder_path, "StormEvents_details-ftp_v1.0_d2025_c20260323.csv.gz")
fatalities_file <- file.path(folder_path, "StormEvents_fatalities-ftp_v1.0_d2025_c20260323.csv.gz")
locations_file <- file.path(folder_path, "StormEvents_locations-ftp_v1.0_d2025_c20260323.csv.gz")
details <- read_csv(details_file, show_col_types = FALSE)
fatalities <- read_csv(fatalities_file, show_col_types = FALSE)
locations <- read_csv(locations_file, show_col_types = FALSE)The three files are linked by EVENT_ID. A left join is
used so that all events in the details file are retained, even if they
have no associated fatalities or location records.
joined_data <- details %>%
left_join(locations, by = "EVENT_ID") %>%
left_join(fatalities, by = "EVENT_ID")
# Save the joined dataset for reference
output_file <- file.path(folder_path, "StormEvents_joined_data.csv")
write_csv(joined_data, output_file)
message("Joined data saved to: ", output_file)
# Preview
glimpse(joined_data)## Rows: 94,364
## Columns: 70
## $ BEGIN_YEARMONTH <dbl> 202503, 202503, 202501, 202501, 202501, 202501, 202…
## $ BEGIN_DAY <dbl> 31, 30, 5, 3, 3, 3, 3, 3, 3, 3, 19, 13, 13, 13, 13,…
## $ BEGIN_TIME <dbl> 1104, 1552, 1800, 1300, 1300, 1300, 1547, 1527, 130…
## $ END_YEARMONTH <dbl> 202503, 202503, 202501, 202501, 202501, 202501, 202…
## $ END_DAY <dbl> 31, 30, 6, 3, 3, 3, 3, 3, 3, 3, 19, 13, 13, 13, 13,…
## $ END_TIME <dbl> 1106, 1555, 2227, 1900, 1900, 1900, 1619, 1619, 190…
## $ EPISODE_ID.x <dbl> 201366, 200337, 197733, 197761, 197761, 197761, 197…
## $ EVENT_ID <dbl> 1252415, 1241136, 1222851, 1223112, 1223113, 122311…
## $ STATE <chr> "GEORGIA", "MICHIGAN", "VIRGINIA", "MARYLAND", "MAR…
## $ STATE_FIPS <dbl> 13, 26, 51, 24, 24, 24, 24, 51, 24, 24, 27, 27, 27,…
## $ YEAR <dbl> 2025, 2025, 2025, 2025, 2025, 2025, 2025, 2025, 202…
## $ MONTH_NAME <chr> "March", "March", "January", "January", "January", …
## $ EVENT_TYPE <chr> "Thunderstorm Wind", "Tornado", "Winter Storm", "Wi…
## $ CZ_TYPE <chr> "C", "C", "Z", "Z", "Z", "Z", "Z", "Z", "Z", "Z", "…
## $ CZ_FIPS <dbl> 45, 27, 56, 506, 504, 503, 14, 53, 5, 505, 89, 71, …
## $ CZ_NAME <chr> "CARROLL", "CASS", "SPOTSYLVANIA", "CENTRAL AND SOU…
## $ WFO <chr> "FFC", "IWX", "LWX", "LWX", "LWX", "LWX", "LWX", "L…
## $ BEGIN_DATE_TIME <chr> "31-MAR-25 11:04:00", "30-MAR-25 15:52:00", "05-JAN…
## $ CZ_TIMEZONE <chr> "EST-5", "EST-5", "EST-5", "EST-5", "EST-5", "EST-5…
## $ END_DATE_TIME <chr> "31-MAR-25 11:06:00", "30-MAR-25 15:55:00", "06-JAN…
## $ INJURIES_DIRECT <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ INJURIES_INDIRECT <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ DEATHS_DIRECT <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ DEATHS_INDIRECT <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ DAMAGE_PROPERTY <chr> "1.00K", "100.00K", NA, NA, NA, NA, "0.00K", NA, NA…
## $ DAMAGE_CROPS <chr> NA, "0.00K", NA, NA, NA, NA, "0.00K", NA, NA, NA, "…
## $ SOURCE <chr> "Emergency Manager", "NWS Storm Survey", "Trained S…
## $ MAGNITUDE <dbl> 52.0, NA, NA, NA, NA, NA, NA, NA, NA, NA, 38.0, NA,…
## $ MAGNITUDE_TYPE <chr> "EG", NA, NA, NA, NA, NA, NA, NA, NA, NA, "MS", NA,…
## $ FLOOD_CAUSE <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ CATEGORY <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ TOR_F_SCALE <chr> NA, "EF1", NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ TOR_LENGTH <dbl> NA, 2.59, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ TOR_WIDTH <dbl> NA, 100, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ TOR_OTHER_WFO <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ TOR_OTHER_CZ_STATE <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ TOR_OTHER_CZ_FIPS <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ TOR_OTHER_CZ_NAME <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ BEGIN_RANGE <dbl> 2.22, 1.24, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ BEGIN_AZIMUTH <chr> "W", "SW", NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
## $ BEGIN_LOCATION <chr> "TYUS", "EDWARDSBURG", NA, NA, NA, NA, NA, NA, NA, …
## $ END_RANGE <dbl> 2.22, 1.47, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ END_AZIMUTH <chr> "W", "NNE", NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ END_LOCATION <chr> "TYUS", "EDWARDSBURG", NA, NA, NA, NA, NA, NA, NA, …
## $ BEGIN_LAT <dbl> 33.4757, 41.7900, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ BEGIN_LON <dbl> -85.238, -86.100, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ END_LAT <dbl> 33.4757, 41.8200, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ END_LON <dbl> -85.238, -86.070, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ EPISODE_NARRATIVE <chr> "A cold-front initiated a line of thunderstorms acr…
## $ EVENT_NARRATIVE <chr> "Tree down at the intersection of highway 5 and old…
## $ DATA_SOURCE <chr> "CSV", "CSV", "CSV", "CSV", "CSV", "CSV", "CSV", "C…
## $ YEARMONTH <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ EPISODE_ID.y <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ LOCATION_INDEX <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ RANGE <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ AZIMUTH <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ LOCATION <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ LATITUDE <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ LONGITUDE <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ LAT2 <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ LON2 <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ FAT_YEARMONTH <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ FAT_DAY <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ FAT_TIME <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ FATALITY_ID <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ FATALITY_TYPE <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ FATALITY_DATE <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ FATALITY_AGE <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ FATALITY_SEX <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
## $ FATALITY_LOCATION <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
# Standardize column names to uppercase for consistency
names(joined_data) <- toupper(names(joined_data))
# Parse the begin date and extract month
# NOAA dates can appear as "01-JAN-25 00:00:00" or "1/1/2025 0:00:00"
# We try multiple formats and fall back to BEGIN_YEARMONTH if needed
joined_data <- joined_data %>%
mutate(
BEGIN_DATE_TIME_PARSED = parse_date_time(
BEGIN_DATE_TIME,
orders = c("dmy HMS", "mdy HMS", "dmy HM", "mdy HM", "dmy", "mdy"),
quiet = TRUE
),
# If parse_date_time failed, extract month directly from BEGIN_YEARMONTH (format: YYYYMM)
MONTH_NUM = case_when(
!is.na(BEGIN_DATE_TIME_PARSED) ~ month(BEGIN_DATE_TIME_PARSED),
!is.na(BEGIN_YEARMONTH) ~ as.integer(BEGIN_YEARMONTH) %% 100L,
TRUE ~ NA_integer_
),
MONTH = month(MONTH_NUM, label = TRUE, abbr = TRUE)
)
# Convert damage columns: handle suffix K (thousands), M (millions), B (billions)
parse_damage <- function(x) {
x <- toupper(trimws(as.character(x)))
multiplier <- case_when(
grepl("K$", x) ~ 1e3,
grepl("M$", x) ~ 1e6,
grepl("B$", x) ~ 1e9,
TRUE ~ 1
)
numeric_part <- as.numeric(gsub("[^0-9.]", "", x))
ifelse(is.na(numeric_part), 0, numeric_part * multiplier)
}
joined_data <- joined_data %>%
mutate(
DAMAGE_PROPERTY_NUM = parse_damage(DAMAGE_PROPERTY),
DAMAGE_CROPS_NUM = parse_damage(DAMAGE_CROPS),
TOTAL_DAMAGE = DAMAGE_PROPERTY_NUM + DAMAGE_CROPS_NUM,
INJURIES_DIRECT = replace_na(INJURIES_DIRECT, 0),
INJURIES_INDIRECT = replace_na(INJURIES_INDIRECT, 0),
DEATHS_DIRECT = replace_na(DEATHS_DIRECT, 0),
DEATHS_INDIRECT = replace_na(DEATHS_INDIRECT, 0),
TOTAL_INJURIES = INJURIES_DIRECT + INJURIES_INDIRECT,
TOTAL_DEATHS = DEATHS_DIRECT + DEATHS_INDIRECT
)
cat("Rows in joined dataset:", nrow(joined_data), "\n")## Rows in joined dataset: 94364
## Unique event types: 48
## States covered: 68
## Rows with valid MONTH: 94364
##
## Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
## 6217 7953 7934 9447 11793 13859 15590 7196 3949 2468 2855 5103
Population health impact is measured by combining total fatalities and total injuries across all recorded events for each event type.
health_summary <- joined_data %>%
group_by(EVENT_TYPE) %>%
summarise(
Total_Deaths = sum(TOTAL_DEATHS, na.rm = TRUE),
Total_Injuries = sum(TOTAL_INJURIES, na.rm = TRUE),
Total_Impact = Total_Deaths + Total_Injuries,
.groups = "drop"
) %>%
arrange(desc(Total_Impact)) %>%
slice_head(n = 15) %>%
pivot_longer(cols = c(Total_Deaths, Total_Injuries),
names_to = "Impact_Type", values_to = "Count") %>%
mutate(EVENT_TYPE = fct_reorder(EVENT_TYPE, Count, .fun = sum))
ggplot(health_summary, aes(x = Count, y = EVENT_TYPE, fill = Impact_Type)) +
geom_col(position = "stack") +
scale_fill_manual(values = c("Total_Deaths" = "#c0392b", "Total_Injuries" = "#e67e22"),
labels = c("Fatalities", "Injuries")) +
scale_x_continuous(labels = comma) +
labs(
title = "Top 15 Most Harmful Storm Event Types: Population Health Impact (2025)",
subtitle = "Stacked bars show fatalities (red) and injuries (orange)",
x = "Total Count (Fatalities + Injuries)",
y = "Event Type",
fill = "Impact Type",
caption = "Source: NOAA Storm Events Database, 2025"
) +
theme_minimal(base_size = 13) +
theme(legend.position = "bottom",
plot.title = element_text(face = "bold"))Figure 1: Top 15 storm event types ranked by total population health impact (fatalities + injuries) in 2025. Tornadoes and thunderstorm winds consistently dominate health-related storm impacts.
Interpretation: The event types with the greatest population health impact are those that are both common and difficult to avoid, such as tornadoes, thunderstorm winds, flash floods, and heat events. Fatalities, though fewer in count than injuries, represent irreversible harm and deserve particular attention in emergency planning.
This analysis examines the geographic distribution of storm events. We identify the top event type per state by frequency.
# Total events per state (top 15)
state_totals <- joined_data %>%
filter(!is.na(STATE)) %>%
count(STATE, name = "Event_Count") %>%
arrange(desc(Event_Count)) %>%
slice_head(n = 15) %>%
mutate(STATE = fct_reorder(STATE, Event_Count))
ggplot(state_totals, aes(x = Event_Count, y = STATE, fill = Event_Count)) +
geom_col() +
scale_fill_gradient(low = "#aed6f1", high = "#1a5276") +
scale_x_continuous(labels = comma) +
labs(
title = "Top 15 States by Total Recorded Storm Events (2025)",
x = "Number of Events",
y = "State",
fill = "Event Count",
caption = "Source: NOAA Storm Events Database, 2025"
) +
theme_minimal(base_size = 13) +
theme(legend.position = "none",
plot.title = element_text(face = "bold"))Figure 2: Top 10 states by total number of storm events recorded in 2025. States in the central and southeastern U.S. tend to experience the highest event counts.
# Most common event type within top 15 states
top_states <- state_totals$STATE
state_event_type <- joined_data %>%
filter(STATE %in% levels(top_states)) %>%
count(STATE, EVENT_TYPE) %>%
group_by(STATE) %>%
slice_max(n, n = 1, with_ties = FALSE) %>%
ungroup() %>%
mutate(STATE = factor(STATE, levels = levels(top_states)))
ggplot(state_event_type, aes(x = n, y = STATE, fill = EVENT_TYPE)) +
geom_col() +
labs(
title = "Most Frequent Storm Event Type per State (Top 15 States, 2025)",
x = "Number of Occurrences",
y = "State",
fill = "Dominant Event Type",
caption = "Source: NOAA Storm Events Database, 2025"
) +
theme_minimal(base_size = 13) +
theme(legend.position = "bottom",
legend.text = element_text(size = 9),
plot.title = element_text(face = "bold")) +
guides(fill = guide_legend(nrow = 3))Figure 3: Most common storm event type in each of the top 15 states. This highlights how storm risk profiles differ by region and can guide state-level emergency preparedness priorities.
Interpretation: Storm frequency varies substantially by state. States with large geographic areas or those situated in climatologically active zones (such as tornado alley or the Gulf Coast) tend to record higher event counts. The dominant event type in each state reflects its regional climate profile and should shape local emergency preparedness investments.
This analysis explores the seasonal timing of different storm event types.
# Top 10 event types overall
top_events <- joined_data %>%
count(EVENT_TYPE, sort = TRUE) %>%
slice_head(n = 10) %>%
pull(EVENT_TYPE)
monthly_dist <- joined_data %>%
filter(EVENT_TYPE %in% top_events, !is.na(MONTH)) %>%
count(EVENT_TYPE, MONTH, MONTH_NUM) %>%
mutate(EVENT_TYPE = factor(EVENT_TYPE, levels = top_events))
ggplot(monthly_dist, aes(x = MONTH, y = n, fill = EVENT_TYPE)) +
geom_col(show.legend = FALSE) +
facet_wrap(~ EVENT_TYPE, scales = "free_y", ncol = 2) +
labs(
title = "Monthly Distribution of Top 10 Storm Event Types (2025)",
x = "Month",
y = "Number of Events",
caption = "Source: NOAA Storm Events Database, 2025"
) +
theme_minimal(base_size = 11) +
theme(
strip.text = element_text(face = "bold", size = 9),
axis.text.x = element_text(angle = 45, hjust = 1),
plot.title = element_text(face = "bold")
)Figure 4: Monthly distribution of the top 10 most frequent storm event types. Clear seasonal patterns emerge, with most event types peaking in spring and summer months.
Interpretation: Seasonal patterns are strongly evident in the data. Thunderstorm winds and tornadoes peak in spring and early summer, consistent with atmospheric instability during those months. Winter storms naturally concentrate in December through February. Understanding these seasonal windows is essential for pre-positioning emergency resources and staffing.
Beyond human health, severe weather causes substantial economic damage through property destruction and crop losses. This question examines total economic losses by state.
damage_by_state <- joined_data %>%
filter(!is.na(STATE)) %>%
group_by(STATE) %>%
summarise(
Total_Property_Damage = sum(DAMAGE_PROPERTY_NUM, na.rm = TRUE),
Total_Crop_Damage = sum(DAMAGE_CROPS_NUM, na.rm = TRUE),
Total_Damage = Total_Property_Damage + Total_Crop_Damage,
.groups = "drop"
) %>%
arrange(desc(Total_Damage)) %>%
slice_head(n = 15) %>%
pivot_longer(cols = c(Total_Property_Damage, Total_Crop_Damage),
names_to = "Damage_Type", values_to = "Amount") %>%
mutate(STATE = fct_reorder(STATE, Amount, .fun = sum))
ggplot(damage_by_state, aes(x = Amount, y = STATE, fill = Damage_Type)) +
geom_col(position = "stack") +
scale_x_continuous(labels = label_dollar(scale = 1e-6, suffix = "M")) +
scale_fill_manual(values = c("Total_Property_Damage" = "#2980b9",
"Total_Crop_Damage" = "#27ae60"),
labels = c("Property Damage", "Crop Damage")) +
labs(
title = "Top 15 States by Total Storm-Related Economic Damage (2025)",
subtitle = "Stacked bars show property (blue) and crop (green) damage",
x = "Total Estimated Damage (Millions USD)",
y = "State",
fill = "Damage Type",
caption = "Source: NOAA Storm Events Database, 2025"
) +
theme_minimal(base_size = 13) +
theme(legend.position = "bottom",
plot.title = element_text(face = "bold"))Figure 5: Total estimated economic damage (property + crop) by state for the top 15 highest-impact states in 2025. A small number of states account for the majority of storm-related economic losses.
Interpretation: Economic damage from severe weather is highly concentrated in a few states, often driven by a handful of large-scale events such as major floods or tornadoes. Property damage consistently outweighs crop damage in dollar terms, though agricultural communities may experience crop losses as a more directly life-altering impact. This information can guide federal and state-level infrastructure investment and disaster relief pre-funding.
summary_tbl <- joined_data %>%
group_by(EVENT_TYPE) %>%
summarise(
Events = n(),
Deaths = sum(TOTAL_DEATHS, na.rm = TRUE),
Injuries = sum(TOTAL_INJURIES, na.rm = TRUE),
Damage_USD = sum(TOTAL_DAMAGE, na.rm = TRUE),
.groups = "drop"
) %>%
arrange(desc(Events)) %>%
slice_head(n = 10) %>%
mutate(Damage_USD = dollar(Damage_USD))
kable(summary_tbl,
col.names = c("Event Type", "# Events", "Deaths", "Injuries", "Total Damage"),
caption = "Table 1: Top 10 most frequent storm event types and their health/economic impacts (2025)",
align = c("l", "r", "r", "r", "r"))| Event Type | # Events | Deaths | Injuries | Total Damage |
|---|---|---|---|---|
| Thunderstorm Wind | 22256 | 105 | 158 | $318,779,700 |
| Flash Flood | 20167 | 37430 | 81 | $78,288,453,100 |
| Hail | 9319 | 0 | 8 | $74,087,500 |
| Flood | 7497 | 55 | 20 | $314,134,150 |
| High Wind | 4604 | 9 | 9 | $12,261,600 |
| Winter Weather | 4443 | 47 | 131 | $2,293,500 |
| Drought | 3283 | 0 | 0 | $39,503,250 |
| Winter Storm | 2962 | 65 | 33 | $4,107,750 |
| Heat | 2926 | 429 | 51 | $0 |
| Tornado | 2471 | 441 | 688 | $13,269,143,500 |
## R version 4.5.2 (2025-10-31)
## Platform: aarch64-apple-darwin20
## Running under: macOS Tahoe 26.3.1
##
## Matrix products: default
## BLAS: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
## LAPACK: /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources/lib/libRlapack.dylib; LAPACK version 3.12.1
##
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
##
## time zone: America/New_York
## tzcode source: internal
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] knitr_1.51 scales_1.4.0 tidyr_1.3.2 lubridate_1.9.5
## [5] forcats_1.0.1 ggplot2_4.0.3 readr_2.2.0 dplyr_1.2.1
##
## loaded via a namespace (and not attached):
## [1] bit_4.6.0 gtable_0.3.6 jsonlite_2.0.0 crayon_1.5.3
## [5] compiler_4.5.2 tidyselect_1.2.1 parallel_4.5.2 jquerylib_0.1.4
## [9] yaml_2.3.12 fastmap_1.2.0 R6_2.6.1 labeling_0.4.3
## [13] generics_0.1.4 tibble_3.3.1 bslib_0.9.0 pillar_1.11.1
## [17] RColorBrewer_1.1-3 tzdb_0.5.0 rlang_1.1.7 cachem_1.1.0
## [21] xfun_0.56 sass_0.4.10 S7_0.2.1 bit64_4.6.0-1
## [25] otel_0.2.0 timechange_0.4.0 cli_3.6.5 withr_3.0.2
## [29] magrittr_2.0.4 digest_0.6.39 grid_4.5.2 vroom_1.7.1
## [33] rstudioapi_0.18.0 hms_1.1.4 lifecycle_1.0.5 vctrs_0.7.3
## [37] evaluate_1.0.5 glue_1.8.0 farver_2.1.2 purrr_1.2.1
## [41] rmarkdown_2.30 tools_4.5.2 pkgconfig_2.0.3 htmltools_0.5.9