---
title: "Numbered markers on other plots"
vignette: >
  %\VignetteIndexEntry{Numbered markers on other plots}
  %\VignetteEngine{quarto::html}
  %\VignetteEncoding{UTF-8}
knitr:
  opts_chunk:
    collapse: true
    comment: "#>"
    fig-width: 7
    fig-height: 4
---

Scatter plots and maps are the most obvious choicies where numbered markers
can be used. However, `geom_focus()` needs only an `x` and a `y` position, so it isn't limited to scatter plots. Positions can be continuous, discrete or dates, and can come from your data or from a stat. This article adds numbered markers to line charts, bar charts and distributions.

```{r}
#| label: setup
library(ggplot2)
library(ggindex)
```

## Events on a line chart

To mark events on a time series, put them in their own data frame and pass
it to `geom_focus()` with `data`. Here each event gets the unemployment value
of its date, so the marker sits on the line.

```{r}
#| label: line
events <- data.frame(
  date = as.Date(c("2001-03-01", "2007-12-01", "2008-09-15")),
  event = c(
    "Dot-com recession begins",
    "Great Recession begins",
    "Lehman Brothers collapses"
  )
)
events$unemploy <- approx(economics$date, economics$unemploy, events$date)$y

ggplot(economics, aes(date, unemploy)) +
  geom_line() +
  geom_focus(aes(info = event), data = events) +
  scale_info_discrete("Events") +
  labs(x = NULL, y = "Unemployed (thousands)") +
  theme_minimal()
```

## Bar charts

On a discrete axis, markers sit at the centre of each category. Nudge them
past the end of the bar with `position_nudge()`. Here the bars are
horizontal, so the markers move along `x`.

```{r}
#| label: bar
classes <- as.data.frame(table(class = mpg$class), responseName = "n")

ggplot(classes, aes(n, class)) +
  geom_col(fill = "grey80") +
  geom_focus(
    aes(info = class, focus = n > 40),
    position = position_nudge(x = 3)
  ) +
  scale_info_discrete("Most common") +
  labs(x = "Models", y = NULL) +
  theme_minimal()
```

## Points in a distribution

Number single observations on top of a box plot, such as outliers you want
to name. Observations that share an `info` value share a number: both new
beetles are 2.

```{r}
#| label: box
ggplot(mpg, aes(class, hwy)) +
  geom_boxplot(outliers = FALSE) +
  geom_focus(aes(info = model, focus = hwy > 40)) +
  scale_info_discrete("Outliers") +
  labs(x = NULL, y = "Highway miles per gallon") +
  theme_minimal()
```

## Summary statistics on a distribution

To mark the mean, median and mode on a density curve, compute them first and
look up the height of the curve at each one with `approx()`. Putting the
value in `info` makes the legend double as a table of the statistics.

```{r}
#| label: density
waiting <- faithful$waiting
dens <- density(waiting)
centres <- data.frame(
  stat = c("Mean", "Median", "Mode"),
  x = c(mean(waiting), median(waiting), dens$x[which.max(dens$y)])
)
centres$y <- approx(dens$x, dens$y, centres$x)$y
centres$info <- sprintf("%s: %.1f min", centres$stat, centres$x)

ggplot(faithful, aes(waiting)) +
  geom_density(fill = "grey90") +
  geom_segment(
    aes(x = x, xend = x, y = 0, yend = y),
    data = centres,
    colour = "grey50",
    linetype = "dashed"
  ) +
  geom_focus(aes(x, y, info = info), data = centres) +
  scale_info_discrete(NULL) +
  labs(x = "Minutes to next eruption", y = "Density") +
  theme_minimal()
```

On a cumulative distribution, quantiles are points on the curve: the median
is where it crosses 0.5. Label the markers with the percentage and explain it
in the legend.

```{r}
#| label: ecdf
quartiles <- data.frame(p = c(0.25, 0.5, 0.75))
quartiles$waiting <- quantile(waiting, quartiles$p, type = 1)
quartiles$label <- quartiles$p * 100
quartiles$info <- sprintf(
  "%g%% erupt within %g min",
  quartiles$label,
  quartiles$waiting
)

ggplot(faithful, aes(waiting)) +
  stat_ecdf(geom = "step") +
  geom_focus(aes(y = p, label = label, info = info), data = quartiles) +
  scale_info_discrete("Quartiles") +
  labs(x = "Minutes to next eruption", y = "Cumulative probability") +
  theme_minimal()
```

`type = 1` makes `quantile()` return observed values, so the markers sit on
the steps of the empirical curve.

## Positions from a stat

`geom_focus()` takes a `stat` like other geoms, so markers can show computed
values. With `stat = "summary"` each marker sits at the class mean and shows
it as the label.

```{r}
#| label: summary
ggplot(mpg, aes(class, hwy)) +
  geom_jitter(width = 0.2, height = 0, colour = "grey70") +
  geom_focus(
    aes(label = after_stat(round(y))),
    stat = "summary",
    fun = mean
  ) +
  labs(x = NULL, y = "Highway miles per gallon") +
  theme_minimal()
```

## Other coordinate systems

Markers are placed by the plot's coordinate system, so they follow it. The
bar chart above in polar coordinates:

```{r}
#| label: radial
ggplot(classes, aes(class, n)) +
  geom_col(fill = "grey80") +
  geom_focus(aes(info = class, focus = n > 40)) +
  scale_info_discrete("Most common") +
  coord_radial() +
  labs(x = NULL, y = NULL) +
  theme_minimal()
```
