Enhancing GDP Visualizations Through Interactivity
For this project, I transformed my previous U.S. GDP data visualization (from portfolio1) by incorporating interactivity with the plotly and DT packages. The original version of the project included static ggplot charts that presented GDP trends and business-cycle dynamics. While these visualizations effectively communicated broad patterns, they lacked the ability for users to explore specific time periods, compare exact values, or interactively engage with the data.
To address this, I added two interactive components. First, I used
plotly to convert the static line chart of real GDP levels
into an interactive chart. Users can now hover over data points to view
precise GDP values and dates, zoom into periods of interest (such as
during recessions), and pan across the full historical range. Second, I
transformed the year-over-year GDP growth bar chart into an interactive
plot using plotly, allowing exploration of growth rates over time.
The original chart and dataset can be found here: https://fred.stlouisfed.org/series/GDPC1
# 1) Load & prepare GDP data
gdp <- read_csv("GDPC1.csv", col_types = cols()) %>%
rename(date = observation_date, gdp = GDPC1) %>%
mutate(date = ymd(date))
# 2) Hard-code NBER recessions
recessions <- tribble(
~start, ~end,
"1948-11-01","1949-10-01",
"1953-07-01","1954-05-01",
"1957-08-01","1958-04-01",
"1960-04-01","1961-02-01",
"1969-12-01","1970-11-01",
"1973-11-01","1975-03-01",
"1980-01-01","1980-07-01",
"1981-07-01","1982-11-01",
"1990-07-01","1991-03-01",
"2001-03-01","2001-11-01",
"2007-12-01","2009-06-01",
"2020-02-01","2020-04-01"
) %>%
mutate(across(everything(), ymd))
# 3) Build the plot
gdp_line <- ggplot() +
# recession bars
geom_rect(
data = recessions,
aes(xmin = start, xmax = end, ymin = -Inf, ymax = Inf),
fill = "grey80", alpha = 0.5
) +
# GDP line + legend
geom_line(
data = gdp,
aes(x = date, y = gdp, color = "Real Gross Domestic Product"),
linewidth = 1
) +
scale_color_manual(
name = NULL,
values = "navy"
) +
guides(
color = guide_legend(
override.aes = list(linewidth = 1.5),
direction = "horizontal"
)
) +
# x axis every 5 years
scale_x_date(
breaks = seq(ymd("1950-01-01"), ymd("2020-01-01"), by = "5 years"),
date_labels = "%Y",
expand = c(0, 0)
) +
# y axis 0–24000 by 4000
scale_y_continuous(
breaks = seq(0, 24000, by = 4000),
labels = scales::comma,
limits = c(0, 24000),
expand = c(0, 0)
) +
# titles & caption
labs(
title = "Real Gross Domestic Product",
y = "Billions of Chained 2017 Dollars",
caption = paste(
"Source: U.S. Bureau of Economic Analysis via FRED®",
"Shaded areas indicate U.S. recessions.",
"fred.stlouisfed.org",
sep = "\n"
)
) +
# minimal theme + solid horizontal grid lines
theme_minimal(base_size = 11) +
theme(
legend.position = "top",
panel.grid.major.x = element_blank(),
panel.grid.minor = element_blank(),
panel.grid.major.y = element_line(color = "grey90", size = 0.5),
plot.title = element_text(face = "bold", size = 14, hjust = 0)
) +
coord_cartesian(clip = "off")
ggplotly(gdp_line)
Second graph:
# Data prep
gdp <- read_csv("GDPC1.csv", col_types = cols()) %>%
rename(date = observation_date, gdp = GDPC1) %>%
mutate(date = as_date(date))
gdp_growth <- gdp %>%
arrange(date) %>%
mutate(yoy = (gdp / lag(gdp, 4) - 1) * 100) %>%
drop_na() %>%
# create a factor with exactly the two levels in the right order
mutate(
growth = factor(
if_else(yoy > 0, "Positive", "Negative"),
levels = c("Negative", "Positive")
)
)
recessions <- tribble(
~start, ~end,
"1948-11-01","1949-10-01",
"1953-07-01","1954-05-01",
"1957-08-01","1958-04-01",
"1960-04-01","1961-02-01",
"1969-12-01","1970-11-01",
"1973-11-01","1975-03-01",
"1980-01-01","1980-07-01",
"1981-07-01","1982-11-01",
"1990-07-01","1991-03-01",
"2001-03-01","2001-11-01",
"2007-12-01","2009-06-01",
"2020-02-01","2020-04-01"
) %>% mutate(across(everything(), ymd))
# Plot
gdp_growth_chart <- ggplot() +
geom_rect(
data = recessions,
aes(xmin = start, xmax = end, ymin = -Inf, ymax = Inf),
fill = "grey80", alpha = .5
) +
geom_col(
data = gdp_growth,
aes(x = date, y = yoy, fill = growth),
width = 90
) +
geom_hline(yintercept = 0, color = "grey50") +
scale_x_date(
breaks = seq(as.Date("1950-01-01"), as.Date("2020-01-01"), by = "5 years"),
date_labels = "%Y",
expand = c(0, 0)
) +
scale_y_continuous(
breaks = seq(-10, 12, by = 2),
labels = function(x) paste0(x, "%"),
expand = expansion(mult = c(0, .02))
) +
scale_fill_manual(
name = "Growth",
values = c(
"Negative" = "red",
"Positive" = "springgreen2"
)
) +
labs(
title = "Year-over-Year Growth in Real GDP",
subtitle = "Bars show annual % change; shaded areas are NBER recessions",
x = NULL,
y = "GDP Growth (percent)",
caption = "Source: BEA via FRED®"
) +
theme_minimal(base_size = 11) +
theme(
legend.position = "bottom"
)
ggplotly(gdp_growth_chart)