---
title: "Examples gallery"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{gallery}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
```

```{r setup}
library(ggtrace)
library(ggplot2)
packageVersion("ggplot2")
```

## Highjack layer data

> Example inspired by a [stackoverflow question](https://stackoverflow.com/questions/76985690/in-ggplot2-how-to-remove-all-theme-remove-some-data-but-keep-aspect-ratio-of-t/77146460#77146460):

```{r bars}
bars <- ggplot(mpg, aes(class)) +
  geom_bar(aes(fill = drv), color = "grey")
bars
```

Intercepting the data at draw step to subset bars arbitrarily:

```{r bars-highjacked}
bars_subset <- highjack_args(
  x = bars, method = Geom$draw_layer, cond = 1L,
  values = expression(
    data = data[c(2, 4, 6, 8, 11),]
  )
)
bars_subset
```

## Debug complex `aes()` expressions

> Example adopted from my [rstudio::conf 2022 talk](https://github.com/yjunechoe/ggtrace-rstudioconf2022)

Given a boxplot made with a `geom_boxplot()` layer, suppose that we want to add a second layer annotating the value of the upper whiskers:

```{r boxplot-base}
box_p <- ggplot(data = mtcars) +
  aes(x = factor(cyl), y = mpg) +
  geom_boxplot()
box_p
```

A naive approach would be to add a layer that combines a **boxplot** stat with a **label** geom. But this errors out of the box:

```{r boxplot-anno-error, error = TRUE}
box_p +
  geom_label(stat = "boxplot")
```

The error tells us that the geom is missing some missing aesthetics, so something must be wrong with **the data that the geom receives**. If we inspect this using `layer_before_geom()`, we find that the columns for `y` and `label` are indeed missing in the _Before Geom_ data:

```{r boxplot-anno-debug}
layer_before_geom(last_plot(), i = 2L, error = TRUE, verbose = TRUE)
```

Note that you can more conveniently call `last_layer_errorcontext()` to the same effect:

```{r boxplot-last_layer_errorcontext}
last_layer_errorcontext()
```

Thus, we need to ensure that `y` exists to satisfy both the stat and the geom, and that `label` exists after the statistical transformation step but before the geom sees the data. Crucially, we use the computed variable `ymax` to (re-)map to the `y` and `label` aesthetics.

```{r boxplot-anno-success}
box_p +
  geom_label(
    aes(y = stage(mpg, after_stat = ymax),
        label = after_stat(ymax)),
    stat = "boxplot"
  )
```

Inspecting the after-stat snapshot of the successful plot above, we see that both `y` and `label` are now present at this stage to later satisfy the geom.

```{r boxplot-anno-success-inspect}
layer_before_geom(last_plot(), i = 2L)[, c("y", "ymax", "label")]
```

## Inspect sub-layer data

> Example adopted from [Demystifying delayed aesthetic evaluation](https://yjunechoe.github.io/posts/2022-03-10-ggplot2-delayed-aes-1/)

A bar plot of counts with `geom_bar()` with `stat = "count"` default:

```{r sub-layer-data-bar}
bar_plot <- ggplot(mpg, aes(class, fill = class)) +
  geom_bar() +
  theme(legend.position = "none")
```

State of bar layer's data after the statistical transformation step:

```{r sub-layer-data-after-stat}
layer_after_stat(bar_plot, verbose = TRUE)
```

We can map aesthetics to variables from the after-stat data using `after_stat()`:

```{r sub-layer-data-after-stat-aes}
bar_plot +
  geom_text(
    aes(label = after_stat(count)),
    stat = "count",
    position = position_nudge(y = 1), vjust = 0
  )
```

## Intervene with surgical precision

> Example adopted from a [twitter thread](https://twitter.com/mattansb/status/1506620436771229715?s=20)

Here's a plot in polar coordinates:

```{r polar-plot}
polar_plot <- ggplot(mtcars, aes(hp, mpg)) +
  geom_point() +
  geom_smooth(method = "lm", formula = y ~ x) +
  expand_limits(y = c(0, 60)) +
  coord_polar(start = 0, theta = "y")

polar_plot
```

We can clip the plot panel by highjacking the `Layout$render()` method using the generic workflow function `with_ggtrace()`:

```{r polar-plot-clipped}
with_ggtrace(
  x = polar_plot + theme(aspect.ratio = 1/.48),
  method = Layout$render,
  trace_steps = 5L,
  trace_expr = quote({
    panels[[1]] <- editGrob(panels[[1]], vp = viewport(xscale = c(.48, 1)))
  }),
  out = "g"
)
```

See implementation in [`MSBMisc::crop_coord_polar()`](https://mattansb.github.io/MSBMisc/reference/crop_coord_polar.html).

## Highjack the drawing context

> Example adopted from my [useR! 2022 talk](https://yjunechoe.github.io/ggtrace-user2022/#/for-grid-power-users):

```{r flashy-plot}
library(palmerpenguins)
flashy_plot <- na.omit(palmerpenguins::penguins) |> 
  ggplot(aes(x = species, y = flipper_length_mm)) +
  geom_boxplot(aes(fill = species), width = .7) +
  facet_wrap(~ year)
flashy_plot
```

```{r flashy-highjack}
highjack_return(
  flashy_plot, Geom$draw_panel, cond = TRUE,
  value = quote({
    circ <- circleGrob(y = .25 * ._counter_)
    grobTree( editGrob(circ, gp = gpar(fill = linearGradient())),
              editGrob(returnValue(), vp = viewport(clip = circ)) )
  }))
```

Note the use of the special variable `._counter_`, which increments every time a function/method has been called. See the [tracing context](https://yjunechoe.github.io/ggtrace/reference/ggtrace_highjack_args.html#tracing-context) topic for more details.
