This report compares recorded fatalities, injuries, and property and crop damage across event types in the supplied NOAA Storm Database extract for 1950-2011. Tornadoes account for the largest cumulative number of recorded deaths and injuries over the full period. In the more comparable 1996-2011 period, excessive heat leads fatalities, while tornadoes lead injuries. Flood has the largest recorded combined property and crop damage total, but this ranking depends on one unusually large and internally inconsistent damage entry. Excluding that single record in a sensitivity analysis makes hurricane/typhoon the leading economic category. Drought accounts for the greatest recorded crop damage. The findings describe historical reported impacts by database label; uneven coverage, inconsistent labels, uncertain damage estimates, and unadjusted dollar values limit their interpretation.
The unit of analysis is a database record, which need not represent a distinct storm: one storm can produce records in several places and under several event labels. All records in the supplied file are included in the primary analysis, including U.S. territories and marine reporting areas; results are not restricted to the contiguous states. Population health is measured with fatalities and injuries separately so their different severity remains visible. Their sum is also shown as a descriptive count of recorded adverse health outcomes, without implying equal severity or a count of unique people. Economic impact is measured as reported property damage plus reported crop damage in nominal U.S. dollars. This excludes unrecorded losses and broader effects such as lost output and health costs.
The report reads the original compressed CSV directly; no prepared
dataset is an input. Only knitr and rmarkdown
are needed in addition to base R. To reproduce it in RStudio, install
those packages once, put this .Rmd beside the raw
.csv.bz2, and select Knit -> Knit to
HTML. The code also searches the current user’s Downloads
directory, or an explicit path can be passed with
params = list(data_file = "path/to/file.csv.bz2") to
rmarkdown::render(). Every analysis chunk is displayed with
echo = TRUE; intermediate data and figures are created
within this document.
knitr::opts_chunk$set(
echo = TRUE, cache = FALSE, warning = TRUE, message = TRUE,
fig.align = "center", out.width = "100%", dpi = 140
)
options(scipen = 999, width = 88)
fmt_n <- function(x) formatC(x, format = "f", digits = 0, big.mark = ",")
fmt_b <- function(x) sprintf("$%.2f billion", x / 1e9)
rank_by <- function(x, metric) {
x[order(-x[[metric]], x$EVTYPE), , drop = FALSE]
}
read.csv() decompresses the file through
bzfile(). Column classes are explicit, and columns
unrelated to this analysis are skipped during import to reduce memory
use. EVTYPE, the damage suffixes, and narratives remain
character strings. Missing numeric entries are retained as missing; the
checks below stop the analysis if any health counts or damage mantissas
are missing, non-finite, or negative. Dates must parse successfully, and
record identifiers must be unique.
candidates <- unique(c(
path.expand(params$data_file),
file.path(path.expand("~"), "Downloads", basename(params$data_file)),
file.path(Sys.getenv("USERPROFILE"), "Downloads", basename(params$data_file))
))
available <- candidates[file.exists(candidates)]
if (!length(available)) {
stop("Raw CSV not found. Put it beside this report or set params$data_file.")
}
data_path <- normalizePath(available[1], winslash = "/", mustWork = TRUE)
input_md5 <- unname(tools::md5sum(data_path))
header <- names(read.csv(bzfile(data_path), nrows = 0, check.names = FALSE))
text_fields <- c("BGN_DATE", "STATE", "COUNTYNAME", "EVTYPE",
"PROPDMGEXP", "CROPDMGEXP", "REMARKS")
numeric_fields <- c("FATALITIES", "INJURIES", "PROPDMG", "CROPDMG", "REFNUM")
stopifnot(all(c(text_fields, numeric_fields) %in% header))
classes <- rep("NULL", length(header))
classes[header %in% text_fields] <- "character"
classes[header %in% numeric_fields] <- "numeric"
storm <- read.csv(
bzfile(data_path), colClasses = classes, stringsAsFactors = FALSE,
na.strings = "NA", check.names = FALSE
)
storm$DATE <- as.Date(storm$BGN_DATE, format = "%m/%d/%Y")
storm$YEAR <- as.integer(format(storm$DATE, "%Y"))
stopifnot(!anyNA(storm$DATE), !anyDuplicated(storm$REFNUM))
numeric_audit <- data.frame(
Field = numeric_fields,
Missing = vapply(storm[numeric_fields], function(x) sum(is.na(x)), integer(1)),
Nonfinite = vapply(storm[numeric_fields], function(x) sum(!is.finite(x)), integer(1)),
Negative = vapply(storm[numeric_fields], function(x) sum(x < 0, na.rm = TRUE), integer(1))
)
stopifnot(all(numeric_audit$Nonfinite == 0), all(numeric_audit$Negative == 0))
knitr::kable(numeric_audit, row.names = FALSE,
caption = "Table 1. Validation of imported numeric fields.")
| Field | Missing | Nonfinite | Negative |
|---|---|---|---|
| FATALITIES | 0 | 0 | 0 |
| INJURIES | 0 | 0 | 0 |
| PROPDMG | 0 | 0 | 0 |
| CROPDMG | 0 | 0 | 0 |
| REFNUM | 0 | 0 | 0 |
Labels are converted to uppercase, trimmed, and repeated spaces are
collapsed. No subjective reassignment of mixed events or spelling
variants is performed. For example, TSTM WIND and
THUNDERSTORM WIND, HEAT and
EXCESSIVE HEAT, and FLOOD and
FLASH FLOOD remain distinct. Consequently, the rankings
answer the assignment at the EVTYPE label level rather than
for fully harmonized hazard families. All records are retained,
including records with zero reported impacts.
NOAA’s documentation of the periods of record describes expanded coverage beginning in 1996, with early records concentrated on tornadoes, thunderstorm winds, and hail. Full-period totals answer the question about this supplied file, while a separate 1996-2011 analysis checks how the leaders change during the period with broader event coverage. Neither period provides exposure-adjusted risk or severity per storm.
storm$EVTYPE_RAW <- storm$EVTYPE
storm$EVTYPE <- toupper(gsub("[[:space:]]+", " ", trimws(storm$EVTYPE)))
stopifnot(!anyNA(storm$EVTYPE), all(nzchar(storm$EVTYPE)))
scope <- data.frame(
Item = c("Records", "First event date", "Last event date",
"Original EVTYPE labels", "Normalized EVTYPE labels",
"Records beginning in 1996 or later", "Raw compressed-file MD5"),
Value = c(fmt_n(nrow(storm)), as.character(min(storm$DATE)),
as.character(max(storm$DATE)), fmt_n(length(unique(storm$EVTYPE_RAW))),
fmt_n(length(unique(storm$EVTYPE))), fmt_n(sum(storm$YEAR >= 1996)),
input_md5)
)
knitr::kable(scope, row.names = FALSE, caption = "Table 2. Input and analysis scope.")
| Item | Value |
|---|---|
| Records | 902,297 |
| First event date | 1950-01-03 |
| Last event date | 2011-11-30 |
| Original EVTYPE labels | 985 |
| Normalized EVTYPE labels | 883 |
| Records beginning in 1996 or later | 653,530 |
| Raw compressed-file MD5 | df4aa61fff89427db6b7f7b1113b5553 |
Multipliers are applied before aggregation.
Following the magnitude convention described in NWS
Storm Data Preparation, section 2.7, K, M,
and B denote thousands, millions, and billions of dollars.
The legacy H suffix is interpreted as hundreds; lowercase
letters are accepted after conversion to uppercase. A blank suffix is
treated as dollars (multiplier 1), an explicit assumption checked below.
For numeric or punctuation suffixes with a positive mantissa, the unit
is unresolved and that damage component is set to NA,
rather than guessing a power of ten. A zero mantissa contributes zero
regardless of suffix. Reported sums below omit unresolved components but
retain any interpretable component from the same record, and the
omissions are counted explicitly. Zero means zero recorded damage, not
proof that no damage occurred.
decode_damage <- function(value, suffix) {
suffix <- toupper(trimws(suffix))
multiplier <- setNames(c(1, 1e2, 1e3, 1e6, 1e9), c("", "H", "K", "M", "B"))
dollars <- value * unname(multiplier[match(suffix, names(multiplier))])
dollars[value == 0] <- 0
dollars
}
storm$PROPERTY <- decode_damage(storm$PROPDMG, storm$PROPDMGEXP)
storm$CROPS <- decode_damage(storm$CROPDMG, storm$CROPDMGEXP)
storm$HEALTH <- storm$FATALITIES + storm$INJURIES
suffix_audit <- function(value, suffix, component) {
suffix <- toupper(trimws(suffix))
d <- data.frame(Component = component,
Suffix = ifelse(suffix == "", "[blank]", suffix),
Records = 1L, Positive = as.integer(value > 0),
Unresolved = as.integer(is.na(decode_damage(value, suffix))))
aggregate(cbind(Records, Positive, Unresolved) ~ Component + Suffix,
data = d, FUN = sum)
}
damage_audit <- rbind(
suffix_audit(storm$PROPDMG, storm$PROPDMGEXP, "Property"),
suffix_audit(storm$CROPDMG, storm$CROPDMGEXP, "Crops")
)
unresolved_records <- sum(is.na(storm$PROPERTY) | is.na(storm$CROPS))
knitr::kable(damage_audit, row.names = FALSE,
caption = "Table 3. Suffix audit; Positive counts positive mantissas.")
| Component | Suffix | Records | Positive | Unresolved |
|---|---|---|---|---|
| Property | - | 1 | 1 | 1 |
| Property | ? | 8 | 0 | 0 |
| Property | [blank] | 465934 | 76 | 0 |
| Property | + | 5 | 5 | 5 |
| Property | 0 | 216 | 209 | 209 |
| Property | 1 | 25 | 0 | 0 |
| Property | 2 | 13 | 1 | 1 |
| Property | 3 | 4 | 1 | 1 |
| Property | 4 | 4 | 4 | 4 |
| Property | 5 | 28 | 18 | 18 |
| Property | 6 | 4 | 3 | 3 |
| Property | 7 | 5 | 2 | 2 |
| Property | 8 | 1 | 0 | 0 |
| Property | B | 40 | 40 | 0 |
| Property | H | 7 | 7 | 0 |
| Property | K | 424665 | 227481 | 0 |
| Property | M | 11337 | 11326 | 0 |
| Crops | ? | 7 | 0 | 0 |
| Crops | [blank] | 618413 | 3 | 0 |
| Crops | 0 | 19 | 12 | 12 |
| Crops | 2 | 1 | 0 | 0 |
| Crops | B | 9 | 7 | 0 |
| Crops | K | 281853 | 20158 | 0 |
| Crops | M | 1995 | 1919 | 0 |
There are 256 records with at least one unresolved damage component. The economic figures are therefore sums of interpretable reported components, not complete estimates of all losses. An additional sensitivity treats all blank-suffix components as unresolved to check the dollar assumption without assigning units to numeric suffixes.
The same aggregation function is used for the full file, the 1996 onward subset, and the damage sensitivity analyses. The largest interpretable property-damage record is inspected because one unusual record can dominate national totals. It is retained in the primary results, and a separate analysis excludes the entire record without claiming to know its correct amount. No source value is overwritten.
summarize_events <- function(d) {
out <- aggregate(
d[c("FATALITIES", "INJURIES", "HEALTH", "PROPERTY", "CROPS")],
by = list(EVTYPE = d$EVTYPE), FUN = function(x) sum(x, na.rm = TRUE)
)
counts <- aggregate(
data.frame(Records = rep(1L, nrow(d)),
Unresolved = as.integer(is.na(d$PROPERTY) | is.na(d$CROPS))),
by = list(EVTYPE = d$EVTYPE), FUN = sum
)
out <- merge(out, counts, by = "EVTYPE", sort = FALSE)
out$ECONOMIC <- out$PROPERTY + out$CROPS
out
}
overall <- summarize_events(storm)
recent <- summarize_events(storm[storm$YEAR >= 1996, ])
stopifnot(sum(overall$FATALITIES) == sum(storm$FATALITIES),
sum(overall$INJURIES) == sum(storm$INJURIES),
isTRUE(all.equal(sum(overall$ECONOMIC),
sum(storm$PROPERTY, na.rm = TRUE) +
sum(storm$CROPS, na.rm = TRUE))))
largest_i <- which.max(storm$PROPERTY)
largest_record <- storm[largest_i, c("REFNUM", "DATE", "STATE", "COUNTYNAME",
"EVTYPE", "PROPDMG", "PROPDMGEXP", "CROPDMG",
"CROPDMGEXP", "PROPERTY", "CROPS", "REMARKS")]
without_largest <- summarize_events(storm[-largest_i, ])
recent_without_largest <- summarize_events(
storm[storm$YEAR >= 1996 & seq_len(nrow(storm)) != largest_i, ]
)
blank_sensitive <- storm[c("EVTYPE", "FATALITIES", "INJURIES", "HEALTH",
"PROPERTY", "CROPS")]
blank_sensitive$PROPERTY[trimws(storm$PROPDMGEXP) == ""] <- NA_real_
blank_sensitive$CROPS[trimws(storm$CROPDMGEXP) == ""] <- NA_real_
without_blanks <- summarize_events(blank_sensitive)
blank_difference <- sum(overall$ECONOMIC) - sum(without_blanks$ECONOMIC)
leaders <- function(d, period) {
metrics <- c("FATALITIES", "INJURIES", "HEALTH", "ECONOMIC", "CROPS")
data.frame(
Period = period,
Measure = c("Fatalities", "Injuries", "Fatalities + injuries",
"Property + crop damage", "Crop damage"),
Leader = vapply(metrics, function(m) rank_by(d, m)$EVTYPE[1], character(1)),
Value = vapply(metrics, function(m) max(d[[m]]), numeric(1))
)
}
Tornadoes lead both recorded fatalities and injuries over the full period. They account for 5,633 fatalities and 91,346 injuries, or 62.3% of the combined recorded health outcomes. The table ranks the ten labels with the largest combined counts; the figure ranks deaths and injuries independently so a label with many deaths is not hidden by injury counts.
health_top <- head(rank_by(overall, "HEALTH"), 10)
health_table <- data.frame(
EVTYPE = health_top$EVTYPE,
Fatalities = fmt_n(health_top$FATALITIES),
Injuries = fmt_n(health_top$INJURIES),
`Combined outcomes` = fmt_n(health_top$HEALTH),
check.names = FALSE
)
knitr::kable(health_table, row.names = FALSE,
caption = "Table 4. Largest cumulative recorded health impacts, 1950-2011.")
| EVTYPE | Fatalities | Injuries | Combined outcomes |
|---|---|---|---|
| TORNADO | 5,633 | 91,346 | 96,979 |
| EXCESSIVE HEAT | 1,903 | 6,525 | 8,428 |
| TSTM WIND | 504 | 6,957 | 7,461 |
| FLOOD | 470 | 6,789 | 7,259 |
| LIGHTNING | 816 | 5,230 | 6,046 |
| HEAT | 937 | 2,100 | 3,037 |
| FLASH FLOOD | 978 | 1,777 | 2,755 |
| ICE STORM | 89 | 1,975 | 2,064 |
| THUNDERSTORM WIND | 133 | 1,488 | 1,621 |
| WINTER STORM | 206 | 1,321 | 1,527 |
health_panel <- function(metric, title, color) {
d <- head(rank_by(overall, metric), 10)
d <- d[nrow(d):1, ]
v <- d[[metric]]
mids <- barplot(v, horiz = TRUE, names.arg = d$EVTYPE, las = 1,
col = color, border = NA, cex.names = 0.77,
xlim = c(0, max(v) * 1.27), axes = FALSE,
main = title, xlab = "Recorded people")
ticks <- pretty(c(0, max(v)))
axis(1, at = ticks, labels = fmt_n(ticks), cex.axis = 0.8)
text(v + max(v) * 0.025, mids, labels = fmt_n(v), pos = 4, cex = 0.76)
}
old_par <- par(no.readonly = TRUE)
par(mfrow = c(1, 2), mar = c(4.3, 10.3, 3, 1), mgp = c(2.5, 0.7, 0))
health_panel("FATALITIES", "Fatalities", "#B14A35")
health_panel("INJURIES", "Injuries", "#237B8E")
Figure 1. Ten leading EVTYPE labels by recorded fatalities (left) and injuries (right), 1950-2011. Panels have different horizontal scales; counts are cumulative.
par(old_par)
FLOOD has the largest recorded combined damage
total in the supplied data: $150.32 billion.
HURRICANE/TYPHOON follows at $71.91 billion. Property
damage dominates these totals. For crop damage alone,
DROUGHT leads at $13.97 billion. All
amounts are nominal, with no adjustment for inflation, population, or
wealth.
economic_top <- head(rank_by(overall, "ECONOMIC"), 10)
economic_table <- data.frame(
EVTYPE = economic_top$EVTYPE,
`Property (USD bn)` = round(economic_top$PROPERTY / 1e9, 3),
`Crops (USD bn)` = round(economic_top$CROPS / 1e9, 3),
`Combined (USD bn)` = round(economic_top$ECONOMIC / 1e9, 3),
`Unresolved records` = economic_top$Unresolved, check.names = FALSE
)
knitr::kable(economic_table, row.names = FALSE, digits = 3,
caption = "Table 5. Largest recorded economic impacts, 1950-2011; interpretable components only.")
| EVTYPE | Property (USD bn) | Crops (USD bn) | Combined (USD bn) | Unresolved records |
|---|---|---|---|---|
| FLOOD | 144.658 | 5.662 | 150.320 | 0 |
| HURRICANE/TYPHOON | 69.306 | 2.608 | 71.914 | 0 |
| TORNADO | 56.937 | 0.415 | 57.352 | 14 |
| STORM SURGE | 43.324 | 0.000 | 43.324 | 0 |
| HAIL | 15.732 | 3.026 | 18.758 | 13 |
| FLASH FLOOD | 16.141 | 1.421 | 17.562 | 13 |
| DROUGHT | 1.046 | 13.973 | 15.019 | 0 |
| HURRICANE | 11.868 | 2.742 | 14.610 | 0 |
| RIVER FLOOD | 5.119 | 5.029 | 10.148 | 0 |
| ICE STORM | 3.945 | 5.022 | 8.967 | 1 |
A single damage entry changes the leading category.
The largest property-damage entry is record 605,943, dated 2006-01-01,
for FLOOD in NAPA, CA. Its encoded property damage is $115.00 billion
and it contributes 76.5% of the full-period FLOOD total.
The narrative below describes damage in millions, which conflicts with
the billion-dollar suffix; this supports treating the record as
uncertain. Excluding the record makes HURRICANE/TYPHOON
the largest economic category at $71.91 billion; FLOOD then
totals $35.29 billion. This is a sensitivity check rather than an
asserted correction.
entry_fields <- setdiff(names(largest_record), "REMARKS")
entry_audit <- data.frame(
Field = entry_fields,
Value = vapply(largest_record[entry_fields], as.character, character(1))
)
knitr::kable(entry_audit, row.names = FALSE,
caption = "Table 6. Largest encoded property-damage entry, retained in the primary analysis.")
| Field | Value |
|---|---|
| REFNUM | 605943 |
| DATE | 2006-01-01 |
| STATE | CA |
| COUNTYNAME | NAPA |
| EVTYPE | FLOOD |
| PROPDMG | 115 |
| PROPDMGEXP | B |
| CROPDMG | 32.5 |
| CROPDMGEXP | M |
| PROPERTY | 115000000000 |
| CROPS | 32500000 |
cat(strwrap(gsub("[[:space:]]+", " ", largest_record$REMARKS), width = 84),
sep = "\n")
## Major flooding continued into the early hours of January 1st, before the Napa River
## finally fell below flood stage and the water receeded. Flooding was severe in
## Downtown Napa from the Napa Creek and the City and Parks Department was hit with $6
## million in damage alone. The City of Napa had 600 homes with moderate damage, 150
## damaged businesses with costs of at least $70 million.
economic_panel <- function(summary, title) {
d <- head(rank_by(summary, "ECONOMIC"), 10)
d <- d[nrow(d):1, ]
parts <- rbind(d$PROPERTY, d$CROPS) / 1e9
totals <- colSums(parts)
mids <- barplot(parts, horiz = TRUE, names.arg = d$EVTYPE, las = 1,
col = c("#246B83", "#DEA545"), border = NA,
cex.names = 0.72, xlim = c(0, max(totals) * 1.25),
main = title, xlab = "Damage (US$ billions)")
text(totals + max(totals) * 0.02, mids,
labels = sprintf("%.1f", totals), pos = 4, cex = 0.75)
legend("bottomright", legend = c("Property", "Crops"),
fill = c("#246B83", "#DEA545"), border = NA, bty = "n", cex = 0.8)
}
old_par <- par(no.readonly = TRUE)
par(mfrow = c(1, 2), mar = c(4.3, 10.7, 3, 1), mgp = c(2.5, 0.7, 0))
economic_panel(overall, "All reported records")
economic_panel(without_largest, "Largest damage record excluded")
Figure 2. Ten leading EVTYPE labels by reported property plus crop damage, 1950-2011: all records (left) and excluding the single largest property-damage record (right). Panel scales differ. Values are nominal U.S. dollars; unresolved components are omitted.
par(old_par)
During 1996-2011, EXCESSIVE HEAT leads fatalities at 1,797, while TORNADO leads injuries at 20,667. The change in the fatality leader shows why full-period totals should not be interpreted as a fair comparison of all hazards over a common observation window. The economic leader is FLOOD with all recent records and HURRICANE/TYPHOON when the same unusually large entry is excluded.
period_leaders <- rbind(leaders(overall, "1950-2011"),
leaders(recent, "1996-2011"))
period_leaders$Value <- ifelse(
period_leaders$Measure %in% c("Property + crop damage", "Crop damage"),
fmt_b(period_leaders$Value), fmt_n(period_leaders$Value)
)
knitr::kable(period_leaders, row.names = FALSE,
caption = "Table 7. Leading label for each outcome in two observation periods.")
| Period | Measure | Leader | Value |
|---|---|---|---|
| 1950-2011 | Fatalities | TORNADO | 5,633 |
| 1950-2011 | Injuries | TORNADO | 91,346 |
| 1950-2011 | Fatalities + injuries | TORNADO | 96,979 |
| 1950-2011 | Property + crop damage | FLOOD | $150.32 billion |
| 1950-2011 | Crop damage | DROUGHT | $13.97 billion |
| 1996-2011 | Fatalities | EXCESSIVE HEAT | 1,797 |
| 1996-2011 | Injuries | TORNADO | 20,667 |
| 1996-2011 | Fatalities + injuries | TORNADO | 22,178 |
| 1996-2011 | Property + crop damage | FLOOD | $148.92 billion |
| 1996-2011 | Crop damage | DROUGHT | $13.37 billion |
blank_check <- data.frame(
Assumption = c("Blank suffix = dollars", "Blank suffix omitted"),
Leader = c(rank_by(overall, "ECONOMIC")$EVTYPE[1],
rank_by(without_blanks, "ECONOMIC")$EVTYPE[1]),
`Total interpretable damage (USD bn)` = c(sum(overall$ECONOMIC),
sum(without_blanks$ECONOMIC)) / 1e9,
check.names = FALSE
)
knitr::kable(blank_check, row.names = FALSE, digits = 6,
caption = "Table 8. Sensitivity to the treatment of blank magnitude suffixes.")
| Assumption | Leader | Total interpretable damage (USD bn) |
|---|---|---|
| Blank suffix = dollars | FLOOD | 476.4228 |
| Blank suffix omitted | FLOOD | 476.4228 |
Omitting blank-suffix components reduces the national damage sum by $538, with no change in the leading economic label. Unresolved numeric and punctuation suffixes remain excluded in both versions, so this check does not establish their correct amounts.
These are cumulative recorded impacts rather than predictions, annualized losses, or individual risk estimates. Underreporting, changing collection practices, inconsistent event labels, and uncertainty in damage estimates can affect rankings. The file ends in 2011 and does not describe current conditions. The dollar totals mix prices from different years, and zero reported damage can include unmeasured losses. Separate labels also split related hazards: hurricane wind, flood, and storm surge can arise from the same cyclone but remain separate here. The leading full-period health category is clear in these records, while the economic leader is materially sensitive to one questionable entry. Fatalities and injuries should therefore be read separately, and the economic ranking should be read alongside the sensitivity analysis.
package_versions <- data.frame(
Package = c("knitr", "rmarkdown"),
Version = vapply(c("knitr", "rmarkdown"),
function(p) as.character(utils::packageVersion(p)), character(1))
)
knitr::kable(package_versions, row.names = FALSE)
| Package | Version |
|---|---|
| knitr | 1.52 |
| rmarkdown | 2.32 |
sessionInfo()
## R version 4.5.1 (2025-06-13 ucrt)
## Platform: x86_64-w64-mingw32/x64
## Running under: Windows 11 x64 (build 26300)
##
## Matrix products: default
## LAPACK version 3.12.1
##
## locale:
## [1] LC_COLLATE=Spanish_Spain.utf8 LC_CTYPE=Spanish_Spain.utf8
## [3] LC_MONETARY=Spanish_Spain.utf8 LC_NUMERIC=C
## [5] LC_TIME=Spanish_Spain.utf8
##
## time zone: Europe/Madrid
## tzcode source: internal
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## loaded via a namespace (and not attached):
## [1] digest_0.6.37 R6_2.6.1 fastmap_1.2.0 xfun_0.61
## [5] cachem_1.1.0 knitr_1.52 htmltools_0.5.9 rmarkdown_2.32
## [9] lifecycle_1.0.4 cli_3.6.5 sass_0.4.10 jquerylib_0.1.4
## [13] compiler_4.5.1 rstudioapi_0.19.0 tools_4.5.1 evaluate_1.0.5
## [17] bslib_0.12.0 yaml_2.3.10 rlang_1.3.0 jsonlite_2.0.0