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"
)

Printed Images