---
title: "Getting started with Applr"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Getting started with Applr}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.width = 6,
  fig.height = 4
)
```

A fitted linear model with more than one predictor lives in more dimensions
than a scatterplot can show. The usual workaround, `geom_smooth(method =
"lm")`, quietly fits a *different*, simpler model to the plotted variables, so
the line on the screen is not the model you summarized.

Applr draws the model you actually fit. Its core idea is the **slice**: hold
every predictor except one at a fixed value, and draw the model's predictions
as that one predictor varies. Start by fitting an `lm()`, then hand it to
Applr. Explore it with `autoplot()`, or present it with polish and
fine-grained control using `geom_slice()`.

```{r setup, message = FALSE}
library(Applr)
library(ggplot2)
```

## Explore with autoplot()

`autoplot()` on an `lm` builds the whole plot in one call: the model's own data
as a scatter, a fitted slice line with its confidence ribbon, and a subtitle
saying what the model is. It also prints `summary()` to the console, so you
can refit, re-plot, and read the coefficients and R² in one step (turn this off
with `summary = FALSE`).

```{r}
autoplot(lm(Petal.Length ~ Sepal.Length + I(Sepal.Length^2):Species, iris))
```

`autoplot()` makes a few decisions for you. The model's first numeric
predictor goes on the x-axis, and predictors that group into a few discrete
values become `color`, then facets. Every decision can be overridden. Pass a
`mapping` to change the defaults, just as you would with `ggplot()`; whatever
you leave out is still inferred. Choose a different x-axis with
`aes(x = ...)`. Arguments in `...` pass through to `geom_slice()`, so
`interval = "prediction"` gives the wider ribbon and `interval = "none"` a
bare line.

```{r, results = "hide"}
model <- lm(hwy ~ displ + drv + cyl, data = mpg)

autoplot(model, aes(color = factor(cyl))) + facet_wrap(~drv)

autoplot(model,
         aes(x = cyl, color = factor(drv)),
         interval = "none") +
  labs(title = "The Same Model From a Different Angle")
```

The result is an ordinary ggplot, so `+` works as usual.

## Present with geom_slice()

`geom_slice()` is the layer underneath `autoplot()`. It looks like
`geom_smooth()`, but where `geom_smooth()` fits its own model to the plotted
data, `geom_slice()` draws the model *you* fitted, reading the plot's `aes()`
to learn which predictor is on the x-axis. Unlike `autoplot()`, it makes as
few decisions as it can.

Once a model has more than one predictor, each line is a 2-D slice through it.
Every predictor not on the x-axis has to be held at some value, and
`geom_slice()` fills those values in this order:

- Variables named in `predict_vars` are held at your chosen values.
- Variables mapped to a grouping aesthetic (`aes(color = g)`) are held at each
  group's value, giving one line per group.
- Facet variables are held at each panel's value.
- Anything left over is imputed (mean for numeric, most common value for
  factors), with a console message naming the value used.

The model below has four predictors and was fitted exactly, with no noise. A
bare `geom_slice()` has to impute three of them, and the console messages
report each choice:

```{r, message = TRUE, fig.show = "hold", out.width = "49%", fig.width = 4, fig.height = 3.2}
set.seed(123)
n <- 80
x <- runif(n, 0.1, 10)
x2 <- runif(n, 0.1, 10)
x3 <- sample(c(1, 20, 40), n, replace = TRUE)
x4 <- sample(c(1, 2), n, replace = TRUE)
y <- log(5 + x + x2 + x3 + 1/5 * x * x3 + 80 * x4) # no random noise
dat <- data.frame(x, x2, x3, x4, y)

model <- lm(exp(y) ~ x*x3 + x2 + x4, data = dat)   # exact model fit

ggplot(dat, aes(x, y)) +
  geom_point() +
  geom_slice(model) +
  labs(title = "A Perfectly Fit Model 'Slice'")

# The same model against its full linear predictor: an exact fit
ggplot(dat, aes(x = log(5 + x + x2 + x3 + 1/5 * x * x3 + 80 * x4), y)) +
  geom_point() +
  geom_slice(model) +
  labs(title = "Same Model, Different X-Axis")
```

Notice that the response `exp(y)` was back-transformed onto the plotted `y`
axis without being asked. Those imputations were forced, but you can do better.
Map `x3` to color, facet by `x4`, and show the reach of `x2` as a band, and
every line lands on its points:

```{r}
ggplot(dat, aes(x, y, color = factor(x3))) +
  geom_point() +
  geom_slice(model, band = "x2", predict_vars = list(x2 = c(0, 10))) +
  facet_wrap(~x4) +
  geom_slice_text() +
  geom_slice_subtitle()
```

The rest of this vignette goes through those features one at a time.

### Choosing slices with predict_vars

Give a variable several values in `predict_vars` to draw one line per value.
Several multi-value variables are crossed.

```{r}
model <- lm(Sepal.Length ~ Sepal.Width + Petal.Length, iris)

ggplot(iris, aes(Petal.Length, Sepal.Length)) +
  geom_point() +
  geom_slice(
    model,
    predict_vars = list(Sepal.Width = c(2, 3, 4)),
    interval = "confidence"
  ) +
  geom_slice_text()
```

### Confidence and prediction intervals

`interval = "confidence"` or `"prediction"` shades the corresponding
`predict.lm()` interval around each line:

```{r, fig.show = "hold", out.width = "49%", fig.width = 4, fig.height = 3.2}
model <- lm(hwy ~ displ + I(displ^2), data = mpg)

ggplot(mpg, aes(displ, hwy)) +
  geom_point() +
  geom_slice(model, interval = "confidence") +
  labs(title = "Confidence Interval")

ggplot(mpg, aes(displ, hwy)) +
  geom_point() +
  geom_slice(model, interval = "prediction") +
  labs(title = "Prediction Interval")
```

### Projection bands

An interval shows uncertainty. A `band` shows the *reach of a predictor*: two
edge slices with a translucent ribbon between them. `band = "variable"` spans
that predictor between the values given in `predict_vars`, or across its
observed range if `predict_vars` doesn't mention it. `band = TRUE` infers the
variable when there is only one sensible choice.

```{r}
model <- lm(hwy ~ displ * drv + cyl, data = mpg)

# Inferred: cyl is the only predictor not shown, so it spans 4 to 8
ggplot(mpg, aes(displ, hwy, color = drv)) +
  geom_point() +
  geom_slice(model, band = TRUE) +
  geom_slice_text()

# Specified: cyl from 5 to 7
ggplot(mpg, aes(displ, hwy, color = drv)) +
  geom_point() +
  geom_slice(model, band = "cyl", predict_vars = list(cyl = c(5, 7))) +
  geom_slice_text()
```

`band` cannot be combined with `interval`.

### Transformed responses

If the model's response is transformed but the plot shows something else,
predictions are back-transformed to match the y-axis, and a console message
says so. Turn this off with `back_transform = FALSE`, or pass a function or
name (`exp`, `"log10"`, ...) to override the auto-detection.

```{r, fig.show = "hold", out.width = "33%", fig.width = 2.5, fig.height = 3.2}
model <- lm(log(mpg) ~ disp + hp, data = mtcars)

ggplot(mtcars, aes(disp, mpg)) +
  geom_point() +
  geom_slice(model) +
  labs(title = "normal y axis")

ggplot(mtcars, aes(disp, log(mpg))) +
  geom_point() +
  geom_slice(model) +
  labs(title = "log() y axis")

ggplot(mtcars, aes(disp, mpg)) +
  geom_point() +
  geom_slice(model) +
  scale_y_log10() +
  labs(title = "scale_y_log10() axis")
```

### Grouping: one line per group

With a grouping aesthetic, each group gets its own slice, and each line stops
at the end of its group's data. `full_range = TRUE` extends every line across
the whole panel instead, like `fullrange` in `geom_smooth()`:

```{r, fig.show = "hold", out.width = "49%", fig.width = 4, fig.height = 3.2}
model <- lm(hwy ~ displ + I(displ^2) + displ:drv, data = mpg)

ggplot(mpg, aes(displ, hwy, color = drv)) +
  geom_point() +
  geom_slice(model)

ggplot(mpg, aes(displ, hwy, color = drv)) +
  geom_point() +
  geom_slice(model, full_range = TRUE)
```

## Labeling the slices

Three companion layers describe the slices on the plot itself, so a reader can
tell which line is which and what was held constant. They take no model; they
read everything from the plot's `geom_slice()` layers, so add them *after*
those layers.

`geom_slice_text()` labels the end of each line with the values that define
it. It is most useful with bands and multi-value `predict_vars`:

```{r, fig.width = 7.5}
set.seed(123)
n <- 80
x <- runif(n, -10, 10)
x2 <- runif(n, 0, 4)
g <- factor(sample(c("A", "B"), n, replace = TRUE))
y <- x * ifelse(g == "A", 0.5, 2) + ifelse(g == "A", 5, -5) + 4 * x2 + rnorm(n)
dat <- data.frame(x, x2, g, y)
model <- lm(y ~ x * g + x2, data = dat)

ggplot(dat, aes(x, y)) +
  geom_point(alpha = 0.5) +
  geom_slice(model, predict_vars = list(x2 = c(0, 2, 4), g = c("A", "B"))) +
  geom_slice_text(style = "legend")
```

`geom_slice_subtitle()` (or `geom_slice_caption()`) writes the model equation
and any held values that aren't already shown by the legend, facets, or
`geom_slice_text()`. It indents the equation when there's room and compresses
it when space is tight.

```{r}
model <- lm(Petal.Length ~ Sepal.Length + I(Sepal.Length^2):Species + Sepal.Width, iris)

ggplot(iris, aes(Sepal.Length, Petal.Length, color = Species)) +
  geom_point() +
  geom_slice(model, interval = "confidence") +
  geom_slice_subtitle()
```

## Where to go next

- `?geom_slice` documents every option, including `n`, the number of points
  that make up each line.
- `?geom_slice_text` and `?geom_slice_subtitle` cover label styles,
  placement, and `prepend`/`append` text.
- `?slice_2d` and `?add_slice_2d` draw the same slices in base graphics.
- `?scatter_3d` (or `autoplot(model, type = "3d")`) shows a model with two
  numeric predictors as an interactive 3-D surface.
- `?lm_equation` and `?lm_latex` turn the fitted model into text or LaTeX for
  reports, and `?diagnose` draws the standard residual plots.
