---
title: "Billboard Hot 100 Number Ones"
author: "Ana Luisa Bodevan"
date: 2025-08-26
categories: [ridges, music]
image: 20250826.png
page-navigation: true
execute:
warning: false
message: false
eval: false
format:
html:
code-tools: true
code-fold: true
---
```{r}
############## TIDYTUESDAY WEEK 34
############## BILBOARD HOT 100 NUMBER ONES
############## 1. SETUP
library(pacman)
pacman :: p_load(tidyverse, dplyr, glue, scales, ggtext, showtext,
ggridges, ggrepel, patchwork)
billboard <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/main/data/2025/2025-08-26/billboard.csv')
############## 2. DATA ANALYSIS AND TIDYING
df <- billboard %>%
select(bpm, date) %>%
mutate(decade = case_when(
year(date) <= 1957 ~ "50s",
year(date) >= 1958 & year(date) <= 1967 ~ "1960s",
year(date) >= 1968 & year(date) <= 1977 ~ "1970s",
year(date) >= 1978 & year(date) <= 1987 ~ "1980s",
year(date) >= 1988 & year(date) <= 1997 ~ "1990s",
year(date) >= 1998 & year(date) <= 2007 ~ "2000s",
year(date) >= 2008 ~ "2010s",
TRUE ~ "Other"
)) # Creates decades column and classifies variable
# Create factor for decades
df$decade <- factor(df$decade, levels = c("1960s", "1970s", "1980s", "1990s", "2000s", "2010s"))
# Calculate correlation for each decade
df %>%
group_by(decade) %>%
summarise(
mean_bpm = mean(bpm, na.rm = TRUE),
median_bpm = median(bpm, na.rm = TRUE),
sd_bpm = sd(bpm, na.rm = TRUE),
n = n()
)
# Identify tempo categories
df <- df %>%
mutate(tempo_category = case_when(
bpm < 80 ~ "Slow Ballads",
bpm >= 80 & bpm < 100 ~ "Mid-tempo",
bpm >= 100 & bpm < 120 ~ "Moderate",
bpm >= 120 & bpm < 140 ~ "Uptempo",
bpm >= 140 ~ "Fast/Dance"
))
# Identify tempo trends by decade
tempo_by_decade <- df %>%
count(decade, tempo_category) %>%
group_by(decade) %>%
mutate(percentage = n/sum(n) * 100) %>%
drop_na(percentage, tempo_category)
# Create summary data
decade_summary <- df %>%
group_by(decade) %>%
summarise(mean_bpm = mean(bpm, na.rm = TRUE),
median_bpm = median(bpm, na.rm = TRUE),
count = n())
decade_summary <- decade_summary %>%
mutate(label_vjust = case_when(
decade == "1990s" ~ 1.8, # Below the point for first 113
decade == "2000s" ~ 1.8, # Below the point for second 113
decade == "2010s" ~ -1.5, # Above for 121
TRUE ~ -1.5 # Above for all others
))
############## 3. PLOT
# Aesthetics
font_add_google("Inter", "inter")
showtext_auto()
boogie_colors <- c(
primary = "#FF6B35",
secondary = "#F7931E",
accent1 = "#C41E3A",
accent2 = "#2E86AB",
accent3 = "#A23B72",
accent4 = "#F18F01",
background = "#1A1A1D",
text = "#FFFFFF",
grid = "#404040"
)
decade_colors <- c("1960s" = "#FF6B35", "1970s" = "#F7931E", "1980s" = "#C41E3A",
"1990s" = "#A23B72", "2000s" = "#2E86AB", "2010s" = "#F18F01",
"2020s" = "#00B4D8")
theme_boogie <- function() {
theme_minimal() +
theme(
# Background
plot.background = element_rect(fill = boogie_colors["background"], color = NA),
panel.background = element_rect(fill = boogie_colors["background"], color = NA),
# Grid
panel.grid.major = element_line(color = boogie_colors["grid"], linewidth = 0.3),
panel.grid.minor = element_blank(),
# Text
text = element_text(family = "inter", color = boogie_colors["text"]),
plot.title = element_text(size = 30, face = "bold", hjust = 0.5,
margin = margin(b = 10)),
plot.subtitle = element_text(size = 24, hjust = 0.5,
margin = margin(b = 20),
color = "#CCCCCC"),
axis.title = element_text(size = 18, face = "bold"),
axis.text = element_text(size = 10, color = "#DDDDDD"),
# Legend
legend.background = element_rect(fill = boogie_colors["background"]),
legend.text = element_text(color = boogie_colors["text"]),
legend.title = element_text(color = boogie_colors["text"], face = "bold"),
# Plot margins
plot.margin = margin(20, 20, 20, 20)
)
}
# Plot
ggplot(df, aes(x = bpm, y = decade, fill = decade)) +
geom_density_ridges(alpha = 0.8, scale = 0.9, color = "white", linewidth = 0.5) +
scale_fill_manual(values = decade_colors) +
labs(
title = "THE BEAT EVOLUTION",
subtitle = "How Billboard #1 hits groove through the decades",
x = "BEATS PER MINUTE",
y = "",
caption = "Data: Billboard Hot 100 | Viz: @anabodevan"
) +
theme_boogie() +
theme(
legend.position = "none",
axis.text.y = element_text(size = 12, face = "bold"),
plot.caption = element_text(color = "#888888", size = 9, hjust = 1)
)
ggsave(
filename = file.path("tidytuesday", "2025", "2025-08-26", paste0("20250826", ".png")),
height = 7,
width = 8,
bg = "white",
units = "in",
dpi = 300
)
```