diff --git a/_projects/2025/100562295/100562295.Rmd b/_projects/2025/100562295/100562295.Rmd new file mode 100644 index 00000000..f66bf7ab --- /dev/null +++ b/_projects/2025/100562295/100562295.Rmd @@ -0,0 +1,518 @@ +--- +title: "Final Graph: Storm Warnings" +description: | + A short description of the post. +author: Paloma Navarro +date: 2025-12-15 +output: + distill::distill_article: + self_contained: false +--- + +## Final Graph: Storm Warnings + + + +## Loading libraries + +```{r} +library(tidyverse) +library(janitor) +library(ggplot2) +library(showtext) +library(patchwork) +library(ggstream) +``` + +## Adding fonts + +```{r} +font_add_google("Barlow", "barlow") +font_add_google("Barlow Condensed", "Barlow Condensed") +showtext_auto() +``` + +## Loading data + +```{r} +data_raw <- read_csv("events-US-1980-2024.csv", skip = 2, show_col_types = FALSE) |> + clean_names() +``` + +Loading the data, skipping the two non-data header rows. Use the janitor package clean names function to standardize the name of the columns (lowercase) + +## Recoding and tidying data + +```{r} +data_aggregated <- data_raw |> + mutate(year = str_sub(as.character(begin_date), 1, 4) |> as.numeric()) |> + filter(year >= 1980, year <= 2017) |> + mutate( + disaster_type = case_when( + disaster == "Tropical Cyclone" ~ "HURRICANE", + disaster == "Drought" ~ "DROUGHT", + disaster == "Severe Storm" ~ "SEVERE STORM", + disaster == "Flooding" ~ "FLOODING", + disaster == "Freeze" ~ "FREEZE", + disaster == "Wildfire" ~ "WILDFIRE", + disaster == "Winter Storm" ~ "WINTER STORM", + .default = disaster + ) + ) |> + group_by(year, disaster_type) |> + summarise(n_events = n(), .groups = "drop") |> + complete(year = 1980:2017, disaster_type, fill = list(n_events = 0)) |> + mutate( + disaster_type = factor(disaster_type, levels = c( + "SEVERE STORM", "HURRICANE", "FLOODING", "WILDFIRE", + "FREEZE", "DROUGHT", "WINTER STORM" + )) + ) +``` + +## Manual coordination + +```{r} +WIDTH_FACTOR <- 2 #Width of each year +MAX_WIDTH <- 10 * WIDTH_FACTOR #width of each segment + +#dividing data for each segment +seg1 <- data_aggregated |> filter(year <= 1990) |> mutate(segment = 1) +seg2 <- data_aggregated |> filter(year >= 1990, year <= 2000) |> mutate(segment = 2) +seg3 <- data_aggregated |> filter(year >= 2000, year <= 2010) |> mutate(segment = 3) +seg4 <- data_aggregated |> filter(year >= 2010) |> mutate(segment = 4) + +path_data_base <- bind_rows(seg1, seg2, seg3, seg4) + +#Ordering Y axis position +path_data <- path_data_base |> + arrange(segment, year, desc(disaster_type)) |> #correct order + group_by(segment, year) |> #working on each year per segment + mutate( + SCALE_FACTOR = 1.5, + total_height = sum(n_events) * SCALE_FACTOR, #total height of the disasters in a specific year + center_offset = -total_height / 2, + ymax_cumulative = cumsum(n_events * SCALE_FACTOR), #accumulated sum of events + ymin_cumulative = ymax_cumulative - (n_events * SCALE_FACTOR), + y_centered_min = ymin_cumulative + center_offset, + y_centered_max = ymax_cumulative + center_offset + ) |> + ungroup() |> + mutate( + x_new = case_when( #defining the segments of each year and its order + segment == 1 ~ (1990 - year) * WIDTH_FACTOR, + segment == 2 ~ (year - 1990) * WIDTH_FACTOR, + segment == 3 ~ (2010 - year) * WIDTH_FACTOR, + segment == 4 ~ (year - 2010) * WIDTH_FACTOR + ), + y_offset = case_when( #positioning each segment in the grid + segment == 1 ~ 0, + segment == 2 ~ -22, + segment == 3 ~ -44, + segment == 4 ~ -74 + ), + y_final_min = y_centered_min + y_offset, + y_final_max = y_centered_max + y_offset + ) + +``` + +## Creating curves for stacked area chart + +```{r} + +smooth_segment <- function(df) { + if(nrow(df) < 2) return(data.frame()) #two necessary points to create a curve -> creating a union + df_augmented <- df |> arrange(x_new)#ordered by the established data + x_seq <- seq(min(df$x_new), max(df$x_new), length.out = 400) + smooth_min <- spline(df_augmented$x_new, df_augmented$y_final_min, xout = x_seq, method = "natural") + smooth_max <- spline(df_augmented$x_new, df_augmented$y_final_max, xout = x_seq, method = "natural") #smoothing and creating the curve + data.frame(x_new = x_seq, y_final_min = smooth_min$y, y_final_max = smooth_max$y) +} + +path_data_smooth <- path_data |> + group_by(segment, disaster_type) |> + group_modify(~ smooth_segment(.x)) |> + ungroup() #apply to all segments + +``` + +## Creating connectors of the different segments + +```{r} +connectors_left <- data.frame( + x = 0, xend = 0, + y = c(0, -44), + yend = c(-22, -74) +) + +connectors_right <- data.frame( + x = MAX_WIDTH, xend = MAX_WIDTH, + y = -22, + yend = -44 +) + +``` + +## Defining colors + +```{r} +chart_colors <- c( + "SEVERE STORM" = "#6fcfe4", "HURRICANE" = "#b0bfe0", "FLOODING" = "#fdd870", + "WILDFIRE" = "#b8dda8", "FREEZE" = "#c7d6da", "DROUGHT" = "#f291b8", + "WINTER STORM" = "#d9b3d0" +) +``` + +## Creating diagram "Number of events" + +```{r} +POS_2017 <- 7 * WIDTH_FACTOR #base position of plot + +scale_data <- data.frame( + x = seq(0, 8, length.out = 200) +) %>% + mutate( + base_thickness = x * 0.12, #progressive thickness + wave1 = sin(x * 2) * 0.05, + wave2 = sin(x * 3.5) * 0.03, #creating curves + thickness = base_thickness + wave1 + wave2, #combining line thickness + wave + x_scaled = POS_2017 + 5.5 + x * 0.5, + y_top = -81 + thickness * 3, + y_bottom = -81 - thickness * 3 + ) + +``` + +## Main graph + +```{r} +main_graph <- ggplot() + + geom_vline(xintercept = seq(0, MAX_WIDTH, by = WIDTH_FACTOR), + color = "#e5e3d8", linewidth = 0.3, linetype = "dotted") + + + geom_curve(data = connectors_left, aes(x=x, xend=xend, y=y, yend=yend), + curvature = 0.6, angle = 90, ncp = 15, + color = "#d5d3c8", linewidth = 6, lineend = "round", alpha = 0.5) + + + geom_curve(data = connectors_right, aes(x=x, xend=xend, y=y, yend=yend), + curvature = -0.6, angle = 90, ncp = 15, + color = "#d5d3c8", linewidth = 6, lineend = "round", alpha = 0.5) + #creating the curves that connect segments + + geom_ribbon( + data = path_data_smooth, + aes(x = x_new, ymin = y_final_min, ymax = y_final_max, fill = disaster_type, + group = interaction(segment, disaster_type)), + color = "white", linewidth = 0.15, alpha = 0.9 + ) + #representing each disaster + + scale_fill_manual(values = chart_colors) + + + # Vertical lines + annotate("segment", x = seq(0, 10, by = 1) * WIDTH_FACTOR, y = -8, yend = 8, + color = "grey40", linewidth = 0.4, alpha = 0.6) + + annotate("segment", x = seq(0, 10, by = 1) * WIDTH_FACTOR, y = -30, yend = -14, + color = "grey40", linewidth = 0.4, alpha = 0.6) + + annotate("segment", x = seq(0, 10, by = 1) * WIDTH_FACTOR, y = -54, yend = -34, + color = "grey40", linewidth = 0.4, alpha = 0.6) + + annotate("segment", x = seq(0, 7, by = 1) * WIDTH_FACTOR, y = -90, yend = -59, + color = "grey40", linewidth = 0.4, alpha = 0.6) + + + # Up title + annotate("text", x = MAX_WIDTH + 0.8, y = 6.5, + label = "NUMBER OF\nBILLION-\nDOLLAR\nWEATHER AND\nCLIMATE\nDISASTERS IN\nTHE U.S.", + size = 3, color = "grey20", hjust = 0, vjust = 1, + lineheight = 0.9, fontface = "bold", family = "barlow") + + + # Years annotation- segment 1 + annotate("text", x = 10 * WIDTH_FACTOR, y = -9.5, label = "1980", size = 3, color = "grey22", fontface = "bold", family = "barlow") + + annotate("text", x = 9 * WIDTH_FACTOR, y = -9.5, label = "'81", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 8 * WIDTH_FACTOR, y = -9.5, label = "'82", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 7 * WIDTH_FACTOR, y = -9.5, label = "'83", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 6 * WIDTH_FACTOR, y = -9.5, label = "'84", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 5 * WIDTH_FACTOR, y = -9.5, label = "1985", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 4 * WIDTH_FACTOR, y = -9.5, label = "'86", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 3 * WIDTH_FACTOR, y = -9.5, label = "'87", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 2 * WIDTH_FACTOR, y = -9.5, label = "'88", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 1 * WIDTH_FACTOR, y = -9.5, label = "'89", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 0 * WIDTH_FACTOR, y = -9.5, label = "1990", size = 3, color = "grey22", fontface = "bold", family = "barlow") + + + # Years annotation- segment 2 + annotate("text", x = 1 * WIDTH_FACTOR, y = -31.5, label = "'91", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 2 * WIDTH_FACTOR, y = -31.5, label = "'92", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 3 * WIDTH_FACTOR, y = -31.5, label = "'93", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 4 * WIDTH_FACTOR, y = -31.5, label = "'94", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 5 * WIDTH_FACTOR, y = -31.5, label = "1995", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 6 * WIDTH_FACTOR, y = -31.5, label = "'96", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 7 * WIDTH_FACTOR, y = -31.5, label = "'97", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 8 * WIDTH_FACTOR, y = -31.5, label = "'98", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 9 * WIDTH_FACTOR, y = -31.5, label = "'99", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 10 * WIDTH_FACTOR, y = -31.5, label = "2000", size = 3, color = "grey22", fontface = "bold", family = "barlow") + + + # Years annotation- segment 3 + annotate("text", x = 9 * WIDTH_FACTOR, y = -55.5, label = "'01", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 8 * WIDTH_FACTOR, y = -55.5, label = "'02", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 7 * WIDTH_FACTOR, y = -55.5, label = "'03", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 6 * WIDTH_FACTOR, y = -55.5, label = "'04", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 5 * WIDTH_FACTOR, y = -55.5, label = "2005", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 4 * WIDTH_FACTOR, y = -55.5, label = "'06", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 3 * WIDTH_FACTOR, y = -55.5, label = "'07", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 2 * WIDTH_FACTOR, y = -55.5, label = "'08", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 1 * WIDTH_FACTOR, y = -55.5, label = "'09", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 0 * WIDTH_FACTOR, y = -55.5, label = "2010", size = 3, color = "grey22", fontface = "bold", family = "barlow") + + + # Years annotation- segment 4 + annotate("text", x = 1 * WIDTH_FACTOR, y = -91.5, label = "'11", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 2 * WIDTH_FACTOR, y = -91.5, label = "'12", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 3 * WIDTH_FACTOR, y = -91.5, label = "'13", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 4 * WIDTH_FACTOR, y = -91.5, label = "'14", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 5 * WIDTH_FACTOR, y = -91.5, label = "2015", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = 6 * WIDTH_FACTOR, y = -91.5, label = "'16", size = 3, color = "grey30", family = "barlow") + + annotate("text", x = POS_2017, y = -91.5, label = "2017", size = 3, color = "grey22", fontface = "bold", family = "barlow") + + + # 2017 + annotate("segment", x = POS_2017, y = -90, xend = POS_2017, yend = -59, + color = "grey10", linewidth = 1) + + annotate("point", x = POS_2017, y = c(-67, -78, -82), + color = "grey10", size = 3, shape = 19) + + + # Annotations 2017 + annotate("text", x = POS_2017 + 0.5, y = -60, + label = "IN 2017, THE MOST\nFREQUENT\nDISASTERS WERE:", + size = 3.5, color = "grey30", hjust = 0, vjust = 1, lineheight = 0.8, family = "barlow") + + annotate("text", x = POS_2017 + 0.5, y = -68, + label = "SEVERE STORMS\n[8 EVENTS] ...", + size = 3.2, color = "grey20", hjust = 0, vjust = 0.5, + lineheight = 0.8, fontface = "bold", family = "barlow") + + annotate("text", x = POS_2017 + 0.5, y = -79, + label = "... HURRICANES\n[3 EVENTS] ...", + size = 3.2, color = "grey20", hjust = 0, vjust = 0.5, + lineheight = 0.8, fontface = "bold", family = "barlow") + + annotate("text", x = POS_2017 + 0.5, y = -83, + label = "... AND FLOODING\n[2 EVENTS].", + size = 3.2, color = "grey20", hjust = 0, vjust = 0.5, + lineheight = 0.8, fontface = "bold", family = "barlow") + + + # Type of event + annotate("text", x = POS_2017 + 5.5, y = -60, + label = "TYPE OF EVENT", + fontface = "bold", size = 3.5, color = "grey35", hjust = 0, family = "barlow") + + annotate("rect", xmin = POS_2017 + 5.5, xmax = POS_2017 + 6.5, + ymin = -62.5 + c(0, -1.8, -3.6, -5.4, -7.2, -9.0, -10.8) * 0.8, + ymax = -62.5 + c(1.0, -0.8, -2.6, -4.4, -6.2, -8.0, -9.8) * 0.8, + fill = chart_colors, color = "white", linewidth = 0.2) + + annotate("text", x = POS_2017 + 6.7, + y = -62.5 + c(0.5, -1.3, -3.1, -4.9, -6.7, -8.5, -10.3) * 0.8, + label = c("SEVERE STORM", "HURRICANE", "FLOODING", "WILDFIRE", + "FREEZE", "DROUGHT", "WINTER STORM"), + hjust = 0, size = 2.6, color = "grey40", family = "barlow") + + + # Number of events diagram + geom_ribbon(data = scale_data, aes(x = x_scaled, ymin = y_bottom, ymax = y_top), + fill = "grey70", color = NA) + + annotate("text", x = POS_2017 + 5.5 + 0, y = -85 + 1.75 * 3, label = "0", + size = 2.8, color = "grey20", fontface = "bold", family = "barlow") + + annotate("text", x = POS_2017 + 5.5 + 1.0, y = -85 + 1.95 * 3, label = "2", + size = 2.8, color = "grey20", fontface = "bold", family = "barlow") + + annotate("text", x = POS_2017 + 5.5 + 2.0, y = -85 + 2.20 * 3, label = "4", + size = 2.8, color = "grey20", fontface = "bold", family = "barlow") + + annotate("text", x = POS_2017 + 5.5 + 3.0, y = -85 + 2.45 * 3, label = "6", + size = 2.8, color = "grey20", fontface = "bold", family = "barlow") + + annotate("text", x = POS_2017 + 5.5 + 3.88, y = -85 + 2.7 * 3, label = "8", + size = 2.8, color = "grey20", fontface = "bold", family = "barlow") + + annotate("segment", x = POS_2017 + 9.3, y = -85 + 0.8 * 3, + xend = POS_2017 + 9.3, yend = -85 + 2.2 * 3, + arrow = arrow(length = unit(0.08, "cm"), type = "closed", ends = "both"), + color = "grey10", linewidth = 0.5) + + annotate("text", x = POS_2017 + 9.15, y = -85 + 1.5 * 3, + label = "NUMBER\nOF\nEVENTS", + size = 2.1, color = "grey10", fontface = "bold", + hjust = 1, vjust = 0.5, lineheight = 0.8, family = "barlow") + + + coord_fixed(ratio = 0.3, xlim = c(-5, POS_2017 + 13), ylim = c(-95, 10), expand = FALSE) + + + theme_void() + + theme( + plot.background = element_rect(fill = "#f4f1e4", color = NA), + plot.margin = margin(10, 30, 5, 30), + legend.position = "none", + text = element_text(family = "barlow") + ) + +``` + +## Title and descrption paragrah + +```{r} +text_panel <- ggplot() + + ## STORM WARNINGS a la izquierda + annotate("text", x = 4, y = 0.5, + label = "STORM\nWARNINGS", + size = 17, color = "grey10", hjust = 0, vjust = 0.5, + lineheight = 0.85, fontface = "bold", family = "Barlow Condensed") + + + # Texto descriptivo justo a la derecha de STORM WARNINGS + annotate("text", x = 9, y = 0.5, + label ="EXTREME WEATHER ISbecoming more common, and the economic impact is soaring. Last year\n there were 16 weather events in the U.S. that caused at least $1 billion each in damage,\n according to the National Oceanic and Atmospheric Administration. The cumulative cost was\n $306 billion—easily surpassing the previous one-year record of $215 billion set in 2005. In\n September areport from the nonprofit Universal Ecological Fund, \"The Economics Case for\n Climate Action in the United States,\" estimated that total climate-related economic losses\n and health costs in the U.S. averaged $240 billion a year over the past decade. The authors\n project the annual cost will rise to $360 billion over the next 10 years.—BRIAN O'KEEFE", + size = 3, color = "grey20", hjust = 0, vjust = 0.5, + lineheight = 1.2, family = "barlow") + + + xlim(-5, POS_2017 + 13) + + ylim(0, 1) + + theme_void() + + theme( + plot.background = element_rect(fill = "#f4f1e4", color = NA), + plot.margin = margin(5, 30, 20, 30) + ) +``` + +## Patchwork to create final project + +```{r} +final_plot <- main_graph / text_panel + + plot_layout(heights = c(10, 2)) + +print(final_plot) +``` + +# Improvement + +## Streamplot + +```{r} + +streamplot_improvement <- data_aggregated |> + ggplot(aes(x = year, y = n_events, fill = disaster_type)) + + + geom_stream(type = "ridge", bw = 0.75) + + + scale_fill_manual( + values = chart_colors, + name = "TYPE OF EVENT", + labels = c("SEVERE STORM", "HURRICANE", "FLOODING", "WILDFIRE", + "FREEZE", "DROUGHT", "WINTER STORM") + ) + + + scale_x_continuous(breaks = seq(1980, 2017, by = 5), expand = c(0.02, 0)) + + + + scale_y_continuous( + breaks = seq(0, 15, by = 5), + expand = expansion(mult = c(0.05, 0.1)) + ) + + + + geom_vline(xintercept = c(1980, 2017), + linetype = "dashed", color = "grey40", linewidth = 0.5, alpha = 0.7) + + + labs( + title = "STORM WARNINGS: Billion-Dollar Disasters", + subtitle = "From 28 events in the 1980s to 92 events in the 2010s — a dramatic increase in extreme weather", + x = "Year", + y = "Number of Events", + caption = "Source: National Oceanic and Atmospheric Administration (NOAA)" + ) + + + theme_minimal(base_size = 11, base_family = "barlow") + + theme( + plot.background = element_rect(fill = "#f4f1e4", color = NA), + panel.background = element_rect(fill = "#f4f1e4", color = NA), + panel.grid.major.x = element_line(color = "#e5e3d8", linewidth = 0.3), + panel.grid.major.y = element_line(color = "#e5e3d8", linewidth = 0.3), + panel.grid.minor = element_blank(), + + axis.text.x = element_text(size = 10, color = "grey30"), + axis.text.y = element_text(size = 10, color = "grey30"), + axis.title.x = element_text(size = 10, face = "bold", margin = margin(t = 10)), + axis.title.y = element_text(size = 10, face = "bold", margin = margin(r = 10)), + + plot.title = element_text( + face = "bold", + size = 14, + margin = margin(b = 5), + family = "Barlow Condensed" + ), + plot.title.position = "plot", + plot.subtitle = element_text(size = 10, color = "grey40", margin = margin(b = 12)), + plot.caption = element_text(size = 8, color = "grey50", hjust = 0, margin = margin(t = 10)), + plot.caption.position = "plot", + + legend.position = "right", + legend.title = element_text(face = "bold", size = 9), + legend.text = element_text(size = 8), + legend.key.height = unit(0.7, "cm"), + legend.background = element_rect(fill = "#faf9f9", color = "grey80", linewidth = 0.3) + ) + +streamplot_improvement +``` + +## Same improvement, different colors and visualization + +```{r} +realistic_colors <- c( + "SEVERE STORM" = "#34495e", + "HURRICANE" = "#16a085", + "FLOODING" = "#3498db", + "WILDFIRE" = "#e74c3c", + "FREEZE" = "#c7d6da", + "DROUGHT" = "#e67e22", + "WINTER STORM" = "#95a5a6" +) + + + +bar_plot <- data_aggregated |> + ggplot(aes(x = year, y = n_events, fill = disaster_type)) + + + geom_col(color = "white", linewidth = 0.2) + + + scale_fill_manual( + values = realistic_colors, + name = "Disaster Type" + ) + + + scale_x_continuous( + breaks = seq(1980, 2017, by = 5), + expand = c(0.01, 0) + ) + + + scale_y_continuous( + breaks = seq(0, 20, by = 5), + expand = expansion(mult = c(0, 0.05)) + ) + + + labs( + title = "Billion-Dollar Disasters Are Increasing Over Time (1980-2017)", + subtitle = "Annual events show clear upward trend, particularly in Severe Storms and Flooding", + x = "Year", + y = "Number of Events", + caption = "Source: National Oceanic and Atmospheric Administration (NOAA)" + ) + + + theme_minimal(base_size = 11, base_family = "barlow") + + theme( + panel.background = element_rect(fill = "white", color = NA), + panel.grid.major.y = element_line(color = "grey90", linewidth = 0.3), + panel.grid.major.x = element_blank(), + panel.grid.minor = element_blank(), + + axis.title = element_text(size = 10, face = "bold"), + axis.title.x = element_text(margin = margin(t = 10)), + axis.title.y = element_text(margin = margin(r = 10)), + axis.text = element_text(size = 9, color = "grey30"), + + plot.title = element_text(face = "bold", size = 13, margin = margin(b = 5)), + plot.title.position = "plot", + plot.subtitle = element_text(size = 10, color = "grey40", margin = margin(b = 12)), + plot.caption = element_text(size = 8, color = "grey50", hjust = 0, margin = margin(t = 10)), + plot.caption.position = "plot", + + legend.position = "right", + legend.title = element_text(face = "bold", size = 9), + legend.text = element_text(size = 8), + legend.key.height = unit(0.7, "cm") + ) + +bar_plot +``` diff --git a/_projects/2025/100562295/100562295.html b/_projects/2025/100562295/100562295.html new file mode 100644 index 00000000..23b8b2c0 --- /dev/null +++ b/_projects/2025/100562295/100562295.html @@ -0,0 +1,2069 @@ + + + + +
+ + + + + + + + + + + + + + + +A short description of the post.
+
font_add_google("Barlow", "barlow")
+font_add_google("Barlow Condensed", "Barlow Condensed")
+showtext_auto()
+data_raw <- read_csv("events-US-1980-2024.csv", skip = 2, show_col_types = FALSE) |>
+ clean_names()
+Loading the data, skipping the two non-data header rows. Use the janitor package clean names function to standardize the name of the columns (lowercase)
+data_aggregated <- data_raw |>
+ mutate(year = str_sub(as.character(begin_date), 1, 4) |> as.numeric()) |>
+ filter(year >= 1980, year <= 2017) |>
+ mutate(
+ disaster_type = case_when(
+ disaster == "Tropical Cyclone" ~ "HURRICANE",
+ disaster == "Drought" ~ "DROUGHT",
+ disaster == "Severe Storm" ~ "SEVERE STORM",
+ disaster == "Flooding" ~ "FLOODING",
+ disaster == "Freeze" ~ "FREEZE",
+ disaster == "Wildfire" ~ "WILDFIRE",
+ disaster == "Winter Storm" ~ "WINTER STORM",
+ .default = disaster
+ )
+ ) |>
+ group_by(year, disaster_type) |>
+ summarise(n_events = n(), .groups = "drop") |>
+ complete(year = 1980:2017, disaster_type, fill = list(n_events = 0)) |>
+ mutate(
+ disaster_type = factor(disaster_type, levels = c(
+ "SEVERE STORM", "HURRICANE", "FLOODING", "WILDFIRE",
+ "FREEZE", "DROUGHT", "WINTER STORM"
+ ))
+ )
+WIDTH_FACTOR <- 2 #Width of each year
+MAX_WIDTH <- 10 * WIDTH_FACTOR #width of each segment
+
+#dividing data for each segment
+seg1 <- data_aggregated |> filter(year <= 1990) |> mutate(segment = 1)
+seg2 <- data_aggregated |> filter(year >= 1990, year <= 2000) |> mutate(segment = 2)
+seg3 <- data_aggregated |> filter(year >= 2000, year <= 2010) |> mutate(segment = 3)
+seg4 <- data_aggregated |> filter(year >= 2010) |> mutate(segment = 4)
+
+path_data_base <- bind_rows(seg1, seg2, seg3, seg4)
+
+#Ordering Y axis position
+path_data <- path_data_base |>
+ arrange(segment, year, desc(disaster_type)) |> #correct order
+ group_by(segment, year) |> #working on each year per segment
+ mutate(
+ SCALE_FACTOR = 1.5,
+ total_height = sum(n_events) * SCALE_FACTOR, #total height of the disasters in a specific year
+ center_offset = -total_height / 2,
+ ymax_cumulative = cumsum(n_events * SCALE_FACTOR), #accumulated sum of events
+ ymin_cumulative = ymax_cumulative - (n_events * SCALE_FACTOR),
+ y_centered_min = ymin_cumulative + center_offset,
+ y_centered_max = ymax_cumulative + center_offset
+ ) |>
+ ungroup() |>
+ mutate(
+ x_new = case_when( #defining the segments of each year and its order
+ segment == 1 ~ (1990 - year) * WIDTH_FACTOR,
+ segment == 2 ~ (year - 1990) * WIDTH_FACTOR,
+ segment == 3 ~ (2010 - year) * WIDTH_FACTOR,
+ segment == 4 ~ (year - 2010) * WIDTH_FACTOR
+ ),
+ y_offset = case_when( #positioning each segment in the grid
+ segment == 1 ~ 0,
+ segment == 2 ~ -22,
+ segment == 3 ~ -44,
+ segment == 4 ~ -74
+ ),
+ y_final_min = y_centered_min + y_offset,
+ y_final_max = y_centered_max + y_offset
+ )
+smooth_segment <- function(df) {
+ if(nrow(df) < 2) return(data.frame()) #two necessary points to create a curve -> creating a union
+ df_augmented <- df |> arrange(x_new)#ordered by the established data
+ x_seq <- seq(min(df$x_new), max(df$x_new), length.out = 400)
+ smooth_min <- spline(df_augmented$x_new, df_augmented$y_final_min, xout = x_seq, method = "natural")
+ smooth_max <- spline(df_augmented$x_new, df_augmented$y_final_max, xout = x_seq, method = "natural") #smoothing and creating the curve
+ data.frame(x_new = x_seq, y_final_min = smooth_min$y, y_final_max = smooth_max$y)
+}
+
+path_data_smooth <- path_data |>
+ group_by(segment, disaster_type) |>
+ group_modify(~ smooth_segment(.x)) |>
+ ungroup() #apply to all segments
+connectors_left <- data.frame(
+ x = 0, xend = 0,
+ y = c(0, -44),
+ yend = c(-22, -74)
+)
+
+connectors_right <- data.frame(
+ x = MAX_WIDTH, xend = MAX_WIDTH,
+ y = -22,
+ yend = -44
+)
+chart_colors <- c(
+ "SEVERE STORM" = "#6fcfe4", "HURRICANE" = "#b0bfe0", "FLOODING" = "#fdd870",
+ "WILDFIRE" = "#b8dda8", "FREEZE" = "#c7d6da", "DROUGHT" = "#f291b8",
+ "WINTER STORM" = "#d9b3d0"
+)
+POS_2017 <- 7 * WIDTH_FACTOR #base position of plot
+
+scale_data <- data.frame(
+ x = seq(0, 8, length.out = 200)
+) %>%
+ mutate(
+ base_thickness = x * 0.12, #progressive thickness
+ wave1 = sin(x * 2) * 0.05,
+ wave2 = sin(x * 3.5) * 0.03, #creating curves
+ thickness = base_thickness + wave1 + wave2, #combining line thickness + wave
+ x_scaled = POS_2017 + 5.5 + x * 0.5,
+ y_top = -81 + thickness * 3,
+ y_bottom = -81 - thickness * 3
+ )
+main_graph <- ggplot() +
+ geom_vline(xintercept = seq(0, MAX_WIDTH, by = WIDTH_FACTOR),
+ color = "#e5e3d8", linewidth = 0.3, linetype = "dotted") +
+
+ geom_curve(data = connectors_left, aes(x=x, xend=xend, y=y, yend=yend),
+ curvature = 0.6, angle = 90, ncp = 15,
+ color = "#d5d3c8", linewidth = 6, lineend = "round", alpha = 0.5) +
+
+ geom_curve(data = connectors_right, aes(x=x, xend=xend, y=y, yend=yend),
+ curvature = -0.6, angle = 90, ncp = 15,
+ color = "#d5d3c8", linewidth = 6, lineend = "round", alpha = 0.5) + #creating the curves that connect segments
+
+ geom_ribbon(
+ data = path_data_smooth,
+ aes(x = x_new, ymin = y_final_min, ymax = y_final_max, fill = disaster_type,
+ group = interaction(segment, disaster_type)),
+ color = "white", linewidth = 0.15, alpha = 0.9
+ ) + #representing each disaster
+
+ scale_fill_manual(values = chart_colors) +
+
+ # Vertical lines
+ annotate("segment", x = seq(0, 10, by = 1) * WIDTH_FACTOR, y = -8, yend = 8,
+ color = "grey40", linewidth = 0.4, alpha = 0.6) +
+ annotate("segment", x = seq(0, 10, by = 1) * WIDTH_FACTOR, y = -30, yend = -14,
+ color = "grey40", linewidth = 0.4, alpha = 0.6) +
+ annotate("segment", x = seq(0, 10, by = 1) * WIDTH_FACTOR, y = -54, yend = -34,
+ color = "grey40", linewidth = 0.4, alpha = 0.6) +
+ annotate("segment", x = seq(0, 7, by = 1) * WIDTH_FACTOR, y = -90, yend = -59,
+ color = "grey40", linewidth = 0.4, alpha = 0.6) +
+
+ # Up title
+ annotate("text", x = MAX_WIDTH + 0.8, y = 6.5,
+ label = "NUMBER OF\nBILLION-\nDOLLAR\nWEATHER AND\nCLIMATE\nDISASTERS IN\nTHE U.S.",
+ size = 3, color = "grey20", hjust = 0, vjust = 1,
+ lineheight = 0.9, fontface = "bold", family = "barlow") +
+
+ # Years annotation- segment 1
+ annotate("text", x = 10 * WIDTH_FACTOR, y = -9.5, label = "1980", size = 3, color = "grey22", fontface = "bold", family = "barlow") +
+ annotate("text", x = 9 * WIDTH_FACTOR, y = -9.5, label = "'81", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 8 * WIDTH_FACTOR, y = -9.5, label = "'82", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 7 * WIDTH_FACTOR, y = -9.5, label = "'83", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 6 * WIDTH_FACTOR, y = -9.5, label = "'84", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 5 * WIDTH_FACTOR, y = -9.5, label = "1985", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 4 * WIDTH_FACTOR, y = -9.5, label = "'86", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 3 * WIDTH_FACTOR, y = -9.5, label = "'87", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 2 * WIDTH_FACTOR, y = -9.5, label = "'88", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 1 * WIDTH_FACTOR, y = -9.5, label = "'89", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 0 * WIDTH_FACTOR, y = -9.5, label = "1990", size = 3, color = "grey22", fontface = "bold", family = "barlow") +
+
+ # Years annotation- segment 2
+ annotate("text", x = 1 * WIDTH_FACTOR, y = -31.5, label = "'91", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 2 * WIDTH_FACTOR, y = -31.5, label = "'92", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 3 * WIDTH_FACTOR, y = -31.5, label = "'93", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 4 * WIDTH_FACTOR, y = -31.5, label = "'94", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 5 * WIDTH_FACTOR, y = -31.5, label = "1995", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 6 * WIDTH_FACTOR, y = -31.5, label = "'96", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 7 * WIDTH_FACTOR, y = -31.5, label = "'97", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 8 * WIDTH_FACTOR, y = -31.5, label = "'98", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 9 * WIDTH_FACTOR, y = -31.5, label = "'99", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 10 * WIDTH_FACTOR, y = -31.5, label = "2000", size = 3, color = "grey22", fontface = "bold", family = "barlow") +
+
+ # Years annotation- segment 3
+ annotate("text", x = 9 * WIDTH_FACTOR, y = -55.5, label = "'01", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 8 * WIDTH_FACTOR, y = -55.5, label = "'02", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 7 * WIDTH_FACTOR, y = -55.5, label = "'03", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 6 * WIDTH_FACTOR, y = -55.5, label = "'04", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 5 * WIDTH_FACTOR, y = -55.5, label = "2005", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 4 * WIDTH_FACTOR, y = -55.5, label = "'06", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 3 * WIDTH_FACTOR, y = -55.5, label = "'07", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 2 * WIDTH_FACTOR, y = -55.5, label = "'08", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 1 * WIDTH_FACTOR, y = -55.5, label = "'09", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 0 * WIDTH_FACTOR, y = -55.5, label = "2010", size = 3, color = "grey22", fontface = "bold", family = "barlow") +
+
+ # Years annotation- segment 4
+ annotate("text", x = 1 * WIDTH_FACTOR, y = -91.5, label = "'11", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 2 * WIDTH_FACTOR, y = -91.5, label = "'12", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 3 * WIDTH_FACTOR, y = -91.5, label = "'13", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 4 * WIDTH_FACTOR, y = -91.5, label = "'14", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 5 * WIDTH_FACTOR, y = -91.5, label = "2015", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = 6 * WIDTH_FACTOR, y = -91.5, label = "'16", size = 3, color = "grey30", family = "barlow") +
+ annotate("text", x = POS_2017, y = -91.5, label = "2017", size = 3, color = "grey22", fontface = "bold", family = "barlow") +
+
+ # 2017
+ annotate("segment", x = POS_2017, y = -90, xend = POS_2017, yend = -59,
+ color = "grey10", linewidth = 1) +
+ annotate("point", x = POS_2017, y = c(-67, -78, -82),
+ color = "grey10", size = 3, shape = 19) +
+
+ # Annotations 2017
+ annotate("text", x = POS_2017 + 0.5, y = -60,
+ label = "IN 2017, THE MOST\nFREQUENT\nDISASTERS WERE:",
+ size = 3.5, color = "grey30", hjust = 0, vjust = 1, lineheight = 0.8, family = "barlow") +
+ annotate("text", x = POS_2017 + 0.5, y = -68,
+ label = "SEVERE STORMS\n[8 EVENTS] ...",
+ size = 3.2, color = "grey20", hjust = 0, vjust = 0.5,
+ lineheight = 0.8, fontface = "bold", family = "barlow") +
+ annotate("text", x = POS_2017 + 0.5, y = -79,
+ label = "... HURRICANES\n[3 EVENTS] ...",
+ size = 3.2, color = "grey20", hjust = 0, vjust = 0.5,
+ lineheight = 0.8, fontface = "bold", family = "barlow") +
+ annotate("text", x = POS_2017 + 0.5, y = -83,
+ label = "... AND FLOODING\n[2 EVENTS].",
+ size = 3.2, color = "grey20", hjust = 0, vjust = 0.5,
+ lineheight = 0.8, fontface = "bold", family = "barlow") +
+
+ # Type of event
+ annotate("text", x = POS_2017 + 5.5, y = -60,
+ label = "TYPE OF EVENT",
+ fontface = "bold", size = 3.5, color = "grey35", hjust = 0, family = "barlow") +
+ annotate("rect", xmin = POS_2017 + 5.5, xmax = POS_2017 + 6.5,
+ ymin = -62.5 + c(0, -1.8, -3.6, -5.4, -7.2, -9.0, -10.8) * 0.8,
+ ymax = -62.5 + c(1.0, -0.8, -2.6, -4.4, -6.2, -8.0, -9.8) * 0.8,
+ fill = chart_colors, color = "white", linewidth = 0.2) +
+ annotate("text", x = POS_2017 + 6.7,
+ y = -62.5 + c(0.5, -1.3, -3.1, -4.9, -6.7, -8.5, -10.3) * 0.8,
+ label = c("SEVERE STORM", "HURRICANE", "FLOODING", "WILDFIRE",
+ "FREEZE", "DROUGHT", "WINTER STORM"),
+ hjust = 0, size = 2.6, color = "grey40", family = "barlow") +
+
+ # Number of events diagram
+ geom_ribbon(data = scale_data, aes(x = x_scaled, ymin = y_bottom, ymax = y_top),
+ fill = "grey70", color = NA) +
+ annotate("text", x = POS_2017 + 5.5 + 0, y = -85 + 1.75 * 3, label = "0",
+ size = 2.8, color = "grey20", fontface = "bold", family = "barlow") +
+ annotate("text", x = POS_2017 + 5.5 + 1.0, y = -85 + 1.95 * 3, label = "2",
+ size = 2.8, color = "grey20", fontface = "bold", family = "barlow") +
+ annotate("text", x = POS_2017 + 5.5 + 2.0, y = -85 + 2.20 * 3, label = "4",
+ size = 2.8, color = "grey20", fontface = "bold", family = "barlow") +
+ annotate("text", x = POS_2017 + 5.5 + 3.0, y = -85 + 2.45 * 3, label = "6",
+ size = 2.8, color = "grey20", fontface = "bold", family = "barlow") +
+ annotate("text", x = POS_2017 + 5.5 + 3.88, y = -85 + 2.7 * 3, label = "8",
+ size = 2.8, color = "grey20", fontface = "bold", family = "barlow") +
+ annotate("segment", x = POS_2017 + 9.3, y = -85 + 0.8 * 3,
+ xend = POS_2017 + 9.3, yend = -85 + 2.2 * 3,
+ arrow = arrow(length = unit(0.08, "cm"), type = "closed", ends = "both"),
+ color = "grey10", linewidth = 0.5) +
+ annotate("text", x = POS_2017 + 9.15, y = -85 + 1.5 * 3,
+ label = "NUMBER\nOF\nEVENTS",
+ size = 2.1, color = "grey10", fontface = "bold",
+ hjust = 1, vjust = 0.5, lineheight = 0.8, family = "barlow") +
+
+ coord_fixed(ratio = 0.3, xlim = c(-5, POS_2017 + 13), ylim = c(-95, 10), expand = FALSE) +
+
+ theme_void() +
+ theme(
+ plot.background = element_rect(fill = "#f4f1e4", color = NA),
+ plot.margin = margin(10, 30, 5, 30),
+ legend.position = "none",
+ text = element_text(family = "barlow")
+ )
+text_panel <- ggplot() +
+ ## STORM WARNINGS a la izquierda
+ annotate("text", x = 4, y = 0.5,
+ label = "STORM\nWARNINGS",
+ size = 17, color = "grey10", hjust = 0, vjust = 0.5,
+ lineheight = 0.85, fontface = "bold", family = "Barlow Condensed") +
+
+ # Texto descriptivo justo a la derecha de STORM WARNINGS
+ annotate("text", x = 9, y = 0.5,
+ label ="EXTREME WEATHER ISbecoming more common, and the economic impact is soaring. Last year\n there were 16 weather events in the U.S. that caused at least $1 billion each in damage,\n according to the National Oceanic and Atmospheric Administration. The cumulative cost was\n $306 billion—easily surpassing the previous one-year record of $215 billion set in 2005. In\n September areport from the nonprofit Universal Ecological Fund, \"The Economics Case for\n Climate Action in the United States,\" estimated that total climate-related economic losses\n and health costs in the U.S. averaged $240 billion a year over the past decade. The authors\n project the annual cost will rise to $360 billion over the next 10 years.—BRIAN O'KEEFE",
+ size = 3, color = "grey20", hjust = 0, vjust = 0.5,
+ lineheight = 1.2, family = "barlow") +
+
+ xlim(-5, POS_2017 + 13) +
+ ylim(0, 1) +
+ theme_void() +
+ theme(
+ plot.background = element_rect(fill = "#f4f1e4", color = NA),
+ plot.margin = margin(5, 30, 20, 30)
+ )
+final_plot <- main_graph / text_panel +
+ plot_layout(heights = c(10, 2))
+
+print(final_plot)
+
streamplot_improvement <- data_aggregated |>
+ ggplot(aes(x = year, y = n_events, fill = disaster_type)) +
+
+ geom_stream(type = "ridge", bw = 0.75) +
+
+ scale_fill_manual(
+ values = chart_colors,
+ name = "TYPE OF EVENT",
+ labels = c("SEVERE STORM", "HURRICANE", "FLOODING", "WILDFIRE",
+ "FREEZE", "DROUGHT", "WINTER STORM")
+ ) +
+
+ scale_x_continuous(breaks = seq(1980, 2017, by = 5), expand = c(0.02, 0)) +
+
+
+ scale_y_continuous(
+ breaks = seq(0, 15, by = 5),
+ expand = expansion(mult = c(0.05, 0.1))
+ ) +
+
+
+ geom_vline(xintercept = c(1980, 2017),
+ linetype = "dashed", color = "grey40", linewidth = 0.5, alpha = 0.7) +
+
+ labs(
+ title = "STORM WARNINGS: Billion-Dollar Disasters",
+ subtitle = "From 28 events in the 1980s to 92 events in the 2010s — a dramatic increase in extreme weather",
+ x = "Year",
+ y = "Number of Events",
+ caption = "Source: National Oceanic and Atmospheric Administration (NOAA)"
+ ) +
+
+ theme_minimal(base_size = 11, base_family = "barlow") +
+ theme(
+ plot.background = element_rect(fill = "#f4f1e4", color = NA),
+ panel.background = element_rect(fill = "#f4f1e4", color = NA),
+ panel.grid.major.x = element_line(color = "#e5e3d8", linewidth = 0.3),
+ panel.grid.major.y = element_line(color = "#e5e3d8", linewidth = 0.3),
+ panel.grid.minor = element_blank(),
+
+ axis.text.x = element_text(size = 10, color = "grey30"),
+ axis.text.y = element_text(size = 10, color = "grey30"),
+ axis.title.x = element_text(size = 10, face = "bold", margin = margin(t = 10)),
+ axis.title.y = element_text(size = 10, face = "bold", margin = margin(r = 10)),
+
+ plot.title = element_text(
+ face = "bold",
+ size = 14,
+ margin = margin(b = 5),
+ family = "Barlow Condensed"
+ ),
+ plot.title.position = "plot",
+ plot.subtitle = element_text(size = 10, color = "grey40", margin = margin(b = 12)),
+ plot.caption = element_text(size = 8, color = "grey50", hjust = 0, margin = margin(t = 10)),
+ plot.caption.position = "plot",
+
+ legend.position = "right",
+ legend.title = element_text(face = "bold", size = 9),
+ legend.text = element_text(size = 8),
+ legend.key.height = unit(0.7, "cm"),
+ legend.background = element_rect(fill = "#faf9f9", color = "grey80", linewidth = 0.3)
+ )
+
+streamplot_improvement
+
realistic_colors <- c(
+ "SEVERE STORM" = "#34495e",
+ "HURRICANE" = "#16a085",
+ "FLOODING" = "#3498db",
+ "WILDFIRE" = "#e74c3c",
+ "FREEZE" = "#c7d6da",
+ "DROUGHT" = "#e67e22",
+ "WINTER STORM" = "#95a5a6"
+)
+
+
+
+bar_plot <- data_aggregated |>
+ ggplot(aes(x = year, y = n_events, fill = disaster_type)) +
+
+ geom_col(color = "white", linewidth = 0.2) +
+
+ scale_fill_manual(
+ values = realistic_colors,
+ name = "Disaster Type"
+ ) +
+
+ scale_x_continuous(
+ breaks = seq(1980, 2017, by = 5),
+ expand = c(0.01, 0)
+ ) +
+
+ scale_y_continuous(
+ breaks = seq(0, 20, by = 5),
+ expand = expansion(mult = c(0, 0.05))
+ ) +
+
+ labs(
+ title = "Billion-Dollar Disasters Are Increasing Over Time (1980-2017)",
+ subtitle = "Annual events show clear upward trend, particularly in Severe Storms and Flooding",
+ x = "Year",
+ y = "Number of Events",
+ caption = "Source: National Oceanic and Atmospheric Administration (NOAA)"
+ ) +
+
+ theme_minimal(base_size = 11, base_family = "barlow") +
+ theme(
+ panel.background = element_rect(fill = "white", color = NA),
+ panel.grid.major.y = element_line(color = "grey90", linewidth = 0.3),
+ panel.grid.major.x = element_blank(),
+ panel.grid.minor = element_blank(),
+
+ axis.title = element_text(size = 10, face = "bold"),
+ axis.title.x = element_text(margin = margin(t = 10)),
+ axis.title.y = element_text(margin = margin(r = 10)),
+ axis.text = element_text(size = 9, color = "grey30"),
+
+ plot.title = element_text(face = "bold", size = 13, margin = margin(b = 5)),
+ plot.title.position = "plot",
+ plot.subtitle = element_text(size = 10, color = "grey40", margin = margin(b = 12)),
+ plot.caption = element_text(size = 8, color = "grey50", hjust = 0, margin = margin(t = 10)),
+ plot.caption.position = "plot",
+
+ legend.position = "right",
+ legend.title = element_text(face = "bold", size = 9),
+ legend.text = element_text(size = 8),
+ legend.key.height = unit(0.7, "cm")
+ )
+
+bar_plot
+
`,e.githubCompareUpdatesUrl&&(t+=`View all changes to this article since it was first published.`),t+=` + If you see mistakes or want to suggest changes, please create an issue on GitHub.
+ `);const n=e.journal;return'undefined'!=typeof n&&'Distill'===n.title&&(t+=` +Diagrams and text are licensed under Creative Commons Attribution CC-BY 4.0 with the source available on GitHub, unless noted otherwise. The figures that have been reused from other sources don’t fall under this license and can be recognized by a note in their caption: “Figure from …”.
+ `),'undefined'!=typeof e.publishedDate&&(t+=` +For attribution in academic contexts, please cite this work as
+${e.concatenatedAuthors}, "${e.title}", Distill, ${e.publishedYear}.
+ BibTeX citation
+${m(e)}
+ `),t}var An=Math.sqrt,En=Math.atan2,Dn=Math.sin,Mn=Math.cos,On=Math.PI,Un=Math.abs,In=Math.pow,Nn=Math.LN10,jn=Math.log,Rn=Math.max,qn=Math.ceil,Fn=Math.floor,Pn=Math.round,Hn=Math.min;const zn=['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],Bn=['Jan.','Feb.','March','April','May','June','July','Aug.','Sept.','Oct.','Nov.','Dec.'],Wn=(e)=>10>e?'0'+e:e,Vn=function(e){const t=zn[e.getDay()].substring(0,3),n=Wn(e.getDate()),i=Bn[e.getMonth()].substring(0,3),a=e.getFullYear().toString(),d=e.getUTCHours().toString(),r=e.getUTCMinutes().toString(),o=e.getUTCSeconds().toString();return`${t}, ${n} ${i} ${a} ${d}:${r}:${o} Z`},$n=function(e){const t=Array.from(e).reduce((e,[t,n])=>Object.assign(e,{[t]:n}),{});return t},Jn=function(e){const t=new Map;for(var n in e)e.hasOwnProperty(n)&&t.set(n,e[n]);return t};class Qn{constructor(e){this.name=e.author,this.personalURL=e.authorURL,this.affiliation=e.affiliation,this.affiliationURL=e.affiliationURL,this.affiliations=e.affiliations||[]}get firstName(){const e=this.name.split(' ');return e.slice(0,e.length-1).join(' ')}get lastName(){const e=this.name.split(' ');return e[e.length-1]}}class Gn{constructor(){this.title='unnamed article',this.description='',this.authors=[],this.bibliography=new Map,this.bibliographyParsed=!1,this.citations=[],this.citationsCollected=!1,this.journal={},this.katex={},this.publishedDate=void 0}set url(e){this._url=e}get url(){if(this._url)return this._url;return this.distillPath&&this.journal.url?this.journal.url+'/'+this.distillPath:this.journal.url?this.journal.url:void 0}get githubUrl(){return this.githubPath?'https://github.com/'+this.githubPath:void 0}set previewURL(e){this._previewURL=e}get previewURL(){return this._previewURL?this._previewURL:this.url+'/thumbnail.jpg'}get publishedDateRFC(){return Vn(this.publishedDate)}get updatedDateRFC(){return Vn(this.updatedDate)}get publishedYear(){return this.publishedDate.getFullYear()}get publishedMonth(){return Bn[this.publishedDate.getMonth()]}get publishedDay(){return this.publishedDate.getDate()}get publishedMonthPadded(){return Wn(this.publishedDate.getMonth()+1)}get publishedDayPadded(){return Wn(this.publishedDate.getDate())}get publishedISODateOnly(){return this.publishedDate.toISOString().split('T')[0]}get volume(){const e=this.publishedYear-2015;if(1>e)throw new Error('Invalid publish date detected during computing volume');return e}get issue(){return this.publishedDate.getMonth()+1}get concatenatedAuthors(){if(2 tag. We found the following text: '+t);const n=document.createElement('span');n.innerHTML=e.nodeValue,e.parentNode.insertBefore(n,e),e.parentNode.removeChild(e)}}}}).observe(this,{childList:!0})}}var Ti='undefined'==typeof window?'undefined'==typeof global?'undefined'==typeof self?{}:self:global:window,_i=f(function(e,t){(function(e){function t(){this.months=['jan','feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec'],this.notKey=[',','{','}',' ','='],this.pos=0,this.input='',this.entries=[],this.currentEntry='',this.setInput=function(e){this.input=e},this.getEntries=function(){return this.entries},this.isWhitespace=function(e){return' '==e||'\r'==e||'\t'==e||'\n'==e},this.match=function(e,t){if((void 0==t||null==t)&&(t=!0),this.skipWhitespace(t),this.input.substring(this.pos,this.pos+e.length)==e)this.pos+=e.length;else throw'Token mismatch, expected '+e+', found '+this.input.substring(this.pos);this.skipWhitespace(t)},this.tryMatch=function(e,t){return(void 0==t||null==t)&&(t=!0),this.skipWhitespace(t),this.input.substring(this.pos,this.pos+e.length)==e},this.matchAt=function(){for(;this.input.length>this.pos&&'@'!=this.input[this.pos];)this.pos++;return!('@'!=this.input[this.pos])},this.skipWhitespace=function(e){for(;this.isWhitespace(this.input[this.pos]);)this.pos++;if('%'==this.input[this.pos]&&!0==e){for(;'\n'!=this.input[this.pos];)this.pos++;this.skipWhitespace(e)}},this.value_braces=function(){var e=0;this.match('{',!1);for(var t=this.pos,n=!1;;){if(!n)if('}'==this.input[this.pos]){if(0 =k&&(++x,i=k);if(d[x]instanceof n||d[T-1].greedy)continue;w=T-x,y=e.slice(i,k),v.index-=i}if(v){g&&(h=v[1].length);var S=v.index+h,v=v[0].slice(h),C=S+v.length,_=y.slice(0,S),L=y.slice(C),A=[x,w];_&&A.push(_);var E=new n(o,u?a.tokenize(v,u):v,b,v,f);A.push(E),L&&A.push(L),Array.prototype.splice.apply(d,A)}}}}}return d},hooks:{all:{},add:function(e,t){var n=a.hooks.all;n[e]=n[e]||[],n[e].push(t)},run:function(e,t){var n=a.hooks.all[e];if(n&&n.length)for(var d,r=0;d=n[r++];)d(t)}}},i=a.Token=function(e,t,n,i,a){this.type=e,this.content=t,this.alias=n,this.length=0|(i||'').length,this.greedy=!!a};if(i.stringify=function(e,t,n){if('string'==typeof e)return e;if('Array'===a.util.type(e))return e.map(function(n){return i.stringify(n,t,e)}).join('');var d={type:e.type,content:i.stringify(e.content,t,n),tag:'span',classes:['token',e.type],attributes:{},language:t,parent:n};if('comment'==d.type&&(d.attributes.spellcheck='true'),e.alias){var r='Array'===a.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(d.classes,r)}a.hooks.run('wrap',d);var l=Object.keys(d.attributes).map(function(e){return e+'="'+(d.attributes[e]||'').replace(/"/g,'"')+'"'}).join(' ');return'<'+d.tag+' class="'+d.classes.join(' ')+'"'+(l?' '+l:'')+'>'+d.content+''+d.tag+'>'},!t.document)return t.addEventListener?(t.addEventListener('message',function(e){var n=JSON.parse(e.data),i=n.language,d=n.code,r=n.immediateClose;t.postMessage(a.highlight(d,a.languages[i],i)),r&&t.close()},!1),t.Prism):t.Prism;var d=document.currentScript||[].slice.call(document.getElementsByTagName('script')).pop();return d&&(a.filename=d.src,document.addEventListener&&!d.hasAttribute('data-manual')&&('loading'===document.readyState?document.addEventListener('DOMContentLoaded',a.highlightAll):window.requestAnimationFrame?window.requestAnimationFrame(a.highlightAll):window.setTimeout(a.highlightAll,16))),t.Prism}();e.exports&&(e.exports=n),'undefined'!=typeof Ti&&(Ti.Prism=n),n.languages.markup={comment://,prolog:/<\?[\w\W]+?\?>/,doctype://i,cdata://i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\\1|\\?(?!\1)[\w\W])*\1|[^\s'">=]+))?)*\s*\/?>/i,inside:{tag:{pattern:/^<\/?[^\s>\/]+/i,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=(?:('|")[\w\W]*?(\1)|[^\s>]+)/i,inside:{punctuation:/[=>"']/}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:/?[\da-z]{1,8};/i},n.hooks.add('wrap',function(e){'entity'===e.type&&(e.attributes.title=e.content.replace(/&/,'&'))}),n.languages.xml=n.languages.markup,n.languages.html=n.languages.markup,n.languages.mathml=n.languages.markup,n.languages.svg=n.languages.markup,n.languages.css={comment:/\/\*[\w\W]*?\*\//,atrule:{pattern:/@[\w-]+?.*?(;|(?=\s*\{))/i,inside:{rule:/@[\w-]+/}},url:/url\((?:(["'])(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,selector:/[^\{\}\s][^\{\};]*?(?=\s*\{)/,string:{pattern:/("|')(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1/,greedy:!0},property:/(\b|\B)[\w-]+(?=\s*:)/i,important:/\B!important\b/i,function:/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:]/},n.languages.css.atrule.inside.rest=n.util.clone(n.languages.css),n.languages.markup&&(n.languages.insertBefore('markup','tag',{style:{pattern:/(
+
+
+ ${e.map(l).map((e)=>`
`)}}const Mi=`
+d-citation-list {
+ contain: layout style;
+}
+
+d-citation-list .references {
+ grid-column: text;
+}
+
+d-citation-list .references .title {
+ font-weight: 500;
+}
+`;class Oi extends HTMLElement{static get is(){return'd-citation-list'}connectedCallback(){this.hasAttribute('distill-prerendered')||(this.style.display='none')}set citations(e){x(this,e)}}var Ui=f(function(e){var t='undefined'==typeof window?'undefined'!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{}:window,n=function(){var e=/\blang(?:uage)?-(\w+)\b/i,n=0,a=t.Prism={util:{encode:function(e){return e instanceof i?new i(e.type,a.util.encode(e.content),e.alias):'Array'===a.util.type(e)?e.map(a.util.encode):e.replace(/&/g,'&').replace(/e.length)break tokenloop;if(!(y instanceof n)){c.lastIndex=0;var v=c.exec(y),w=1;if(!v&&f&&x!=d.length-1){if(c.lastIndex=i,v=c.exec(e),!v)break;for(var S=v.index+(g?v[1].length:0),C=v.index+v[0].length,T=x,k=i,p=d.length;T
+
+`);class Ni extends ei(Ii(HTMLElement)){renderContent(){if(this.languageName=this.getAttribute('language'),!this.languageName)return void console.warn('You need to provide a language attribute to your Footnotes
+
+`,!1);class Fi extends qi(HTMLElement){connectedCallback(){super.connectedCallback(),this.list=this.root.querySelector('ol'),this.root.style.display='none'}set footnotes(e){if(this.list.innerHTML='',e.length){this.root.style.display='';for(const t of e){const e=document.createElement('li');e.id=t.id+'-listing',e.innerHTML=t.innerHTML;const n=document.createElement('a');n.setAttribute('class','footnote-backlink'),n.textContent='[\u21A9]',n.href='#'+t.id,e.appendChild(n),this.list.appendChild(e)}}else this.root.style.display='none'}}const Pi=ti('d-hover-box',`
+
+
+