Setup
Replicate Friendly and Wainer aesthetics in ggplot
Recreation: Keeping Aesthetic Choices with Some Changes
data("Nightingale", package = "HistData")
df <- Nightingale |>
select(Date, Disease.rate, Wounds.rate, Other.rate) |>
pivot_longer(-Date, names_to = "cause", values_to = "rate") |>
mutate(
cause = recode(cause,
"Disease.rate" = "Preventable disease",
"Wounds.rate" = "Wounds and injuries",
"Other.rate" = "Other"
),
cause = factor(cause, levels = c("Preventable disease", "Wounds and injuries", "Other"))
)
sc_date <- as.Date("1855-03-01")
p <- ggplot(df, aes(x = Date, y = rate, color = cause, shape = cause)) +
# Required: vertical line to denote the Sanitary Commission
geom_vline(xintercept = sc_date, linewidth = 0.8) +
# Required: ONLY this label, rotated and aligned ON the vertical line
annotate(
"text",
x = sc_date,
y = max(df$rate) * 0.80,
label = "After Sanitary Commission",
angle = 90,
hjust = 0.5, # centers text on the x position (so it sits on the line)
vjust = 0 # prevents sideways drift off the line
) +
geom_line(linewidth = 1.1) +
geom_point(size = 2.6) +
scale_x_date(
breaks = seq(as.Date("1854-04-01"), as.Date("1856-03-01"), by = "3 months"),
date_labels = "%b %Y"
) +
# Extra space above so the rotated label never gets clipped
scale_y_continuous(expand = expansion(mult = c(0.02, 0.20))) +
scale_color_manual(values = c(
"Preventable disease" = "blue",
"Wounds and injuries" = "red",
"Other" = "black"
)) +
scale_shape_manual(values = c(
"Preventable disease" = 16,
"Wounds and injuries" = 17,
"Other" = 15
)) +
labs(
title = "Causes of Mortality of the British Army in the East",
x = "Date",
y = "Annual Death Rate",
color = "<b>Cause of death</b>",
shape = "<b>Cause of death</b>"
) +
theme_classic(base_size = 12) +
theme(
axis.text.x = element_text(angle = 45, hjust = 1),
legend.title = ggtext::element_markdown(),
legend.background = element_rect(fill = "#FAE8C1", color = "black"),
legend.key = element_rect(fill = "#FAE8C1", color = NA)
)
p

Nightingale line plot with readability improvements
data("Nightingale", package = "HistData")
df <- Nightingale |>
select(Date, Disease.rate, Wounds.rate, Other.rate) |>
pivot_longer(-Date, names_to = "cause", values_to = "rate") |>
mutate(
cause = recode(cause,
"Disease.rate" = "Preventable disease",
"Wounds.rate" = "Wounds and injuries",
"Other.rate" = "Other"
),
cause = factor(cause, levels = c("Preventable disease", "Wounds and injuries", "Other"))
)
sc_date <- as.Date("1855-03-01")
p <- ggplot(df, aes(x = Date, y = rate, color = cause, shape = cause)) +
# Required: vertical line to denote the Sanitary Commission
geom_vline(xintercept = sc_date, linewidth = 0.8) +
# Required: only this label, rotated and aligned to sit on the vertical line
annotate(
"text",
x = sc_date,
y = max(df$rate) * 0.80,
label = "After Sanitary Commission",
angle = 90,
hjust = 0.5,
vjust = 0
) +
# Readability change (3): reduce point size slightly so points do not dominate the lines
geom_line(linewidth = 1.1) +
geom_point(size = 2.0) +
# Readability change (2): reduce x-axis crowding by spacing labels every 4 months
scale_x_date(
date_breaks = "4 months",
date_labels = "%b %Y"
) +
# Readability change (1): force y-axis to start at 0 (death rates cannot be negative)
# Also add extra headroom so the rotated label is never clipped
scale_y_continuous(
limits = c(0, NA),
expand = expansion(mult = c(0.02, 0.20))
) +
scale_color_manual(values = c(
"Preventable disease" = "blue",
"Wounds and injuries" = "red",
"Other" = "black"
)) +
scale_shape_manual(values = c(
"Preventable disease" = 16,
"Wounds and injuries" = 17,
"Other" = 15
)) +
labs(
title = "Causes of Mortality of the British Army in the East",
x = "Date",
y = "Annual Death Rate",
color = "<b>Cause of death</b>",
shape = "<b>Cause of death</b>"
) +
theme_classic(base_size = 12) +
# Readability change (4): add subtle horizontal gridlines to help estimate y-values
theme(
panel.grid.major.y = element_line(color = "grey85"),
axis.text.x = element_text(angle = 45, hjust = 1),
legend.title = ggtext::element_markdown(),
legend.background = element_rect(fill = "#FAE8C1", color = "black"),
legend.key = element_rect(fill = "#FAE8C1", color = NA),
# Readability change (5): move legend closer to the data to reduce eye travel
legend.position = c(0.78, 0.72)
)
p

Saving the improved ggplot version at 600 dpi
# Save the image inside the "figures" folder
# 600 dpi as required
# Width is roughly 2x height (similar proportion to original base R figure)
ggsave(
filename = "../figures/nightingale_ggplot.png",
plot = p,
dpi = 600,
width = 15,
height = 7.5,
units = "in"
)