---
title: "Introduction: Marginal Effects at Specific Values"
author: "Daniel Lüdecke"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Introduction: Marginal Effects at Specific Values}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r set-options, echo = FALSE}
knitr::opts_chunk$set(collapse = TRUE, comment = "#>", dev = "png", fig.width = 7, fig.height = 4, message = FALSE, warning = FALSE)
options(width = 800)

if (!requireNamespace("ggplot2", quietly = TRUE) ||
    !requireNamespace("lme4", quietly = TRUE) ||
    !requireNamespace("sjlabelled", quietly = TRUE) ||
    !requireNamespace("sjmisc", quietly = TRUE)) {
  knitr::opts_chunk$set(eval = FALSE)
}
```

# Marginal effects at specific values or levels

This vignettes shows how to calculate marginal effects at specific values or levels for the terms of interest. It is recommended to read the [general introduction](ggeffects.html) first, if you haven't done this yet.

The `terms`-argument not only defines the model terms of interest, but each model term can be limited to certain values. This allows to compute and plot marginal effects for (grouping) terms at specific values only, or to define values for the main effect of interest.

There are several options to define these values, which always should be placed in square brackets directly after the term name and can vary for each model term.

1. Concrete values are separated by a comma: `terms = "c172code [1,3]"`. For factors, you could also use factor levels, e.g. `terms = "Species [setosa,versicolor]"`.

2. Ranges are specified with a colon: `terms = c("c12hour [30:80]", "c172code [1,3]")`. This would plot all values from 30 to 80 for the variable _c12hour_. By default, the step size is 1, i.e. `[1:4]` would create the range `1, 2, 3, 4`. You can choose different step sizes with `by`, e.g. `[1:4 by=.5]`.

3. Convenient shortcuts to calculate common values like mean +/- 1 SD (`terms = "c12hour [meansd]"`), quartiles (`terms = "c12hour [quart]"`) or minumum and maximum values (`terms = "c12hour [minmax]"`). See `values_at()` for the different options.

4. A function name. The function is then applied to all unique values of the indicated variable, e.g. `terms = "hp [exp]"`. You can also define own functions, and pass the name of it to the `terms`-values, e.g. `terms = "hp [own_function]"`.

5. A variable name. The values of the variable are then used to define the `terms`-values, e.g. first, a vector is defined: `v = c(1000, 2000, 3000)` and then, `terms = "income [v]"`.

6. If the _first_ variable specified in `terms` is a _numeric_ vector, for which no specific values are given, a "pretty range" is calculated (see `pretty_range()`), to avoid memory allocation problems for vectors with many unique values. To select all values, use the `[all]`-tag, e.g. `terms = "mpg [all]"`. If a _numeric_ vector is specified as _second_ or _third_ variable in `term` (i.e. if this vector represents a grouping structure), representative values (see `values_at()`) are chosen, which is typically mean +/- SD.

7. To create a pretty range that should be smaller or larger than the default range (i.e. if no specific values would be given), use the `n`-tag, e.g. `terms = "age [n=5]"` or `terms = "age [n = 12]"`. Larger values for `n` return a larger range of predicted values.

8. Especially useful for plotting group levels of random effects with many levels, is the `sample`-option, e.g. `terms = "Subject [sample=9]"`, which will sample nine values from all possible values of the variable `Subject`.

## Specific values and value range

```{r}
library(ggeffects)
library(ggplot2)
data(efc)
fit <- lm(barthtot ~ c12hour + neg_c_7 + c161sex + c172code, data = efc)

mydf <- ggpredict(fit, terms = c("c12hour [30:80]", "c172code [1,3]"))
mydf
ggplot(mydf, aes(x, predicted, colour = group)) + geom_line()
```

Defining value ranges is especially useful when variables are, for instance, log-transformed. `ggpredict()` then typically only uses the range of the log-transformed variable, which is in most cases not what we want. In such situation, specify the range in the `terms`-argument.

```{r}
data(mtcars)
mpg_model <- lm(mpg ~ log(hp), data = mtcars)

# x-values and predictions based on the log(hp)-values
ggpredict(mpg_model, "hp")

# x-values and predictions based on hp-values from 50 to 150
ggpredict(mpg_model, "hp [50:150]")
```

By default, the step size for a range is 1, like `50, 51, 52, ...`. If you need a different step size, use `by=<stepsize>` inside the brackets, e.g. `"hp [50:60 by=.5]"`. This would create a range from 50 to 60, with .5er steps.

```{r}
# range for x-values with .5-steps
ggpredict(mpg_model, "hp [50:60 by=.5]")
```

## Choosing representative values

Especially in situations where we have two continuous variables in interaction terms, or where the "grouping" variable is continuous, it is helpful to select representative values of the grouping variable - else, predictions would be made for too many groups, which is no longer helpful when interpreting marginal effects.

You can use 

* `"minmax"`: minimum and maximum values (lower and upper bounds) of the variable are used.
* `"meansd"`: uses the mean value as well as one standard deviation below and above mean value.
* `"zeromax"`: is similar to the `"minmax"` option, however, 0 is always used as minimum value. This may be useful for predictors that don't have an empirical zero-value.
* `"quart"` calculates and uses the quartiles (lower, median and upper), _including_ minimum and maximum value.
* `"quart2"` calculates and uses the quartiles (lower, median and upper), _excluding_ minimum and maximum value.
* `"all"` takes all values of the vector.

```{r}
data(efc)
# short variable label, for plot
attr(efc$c12hour, "label") <- "hours of care"
fit <- lm(barthtot ~ c12hour * c161sex + neg_c_7, data = efc)

mydf <- ggpredict(fit, terms = c("c161sex", "c12hour [meansd]"))
plot(mydf)

mydf <- ggpredict(fit, terms = c("c161sex", "c12hour [quart]"))
plot(mydf)
```

## Transforming values with functions

The brackets in the `terms`-argument also accept the name of a valid function, to (back-)transform predicted valued. In this example, an alternative would be to specify that values should be exponentiated, which is indicated by `[exp]` in the `terms`-argument:

```{r}
# x-values and predictions based on exponentiated hp-values
ggpredict(mpg_model, "hp [exp]")
```

It is possible to define any function, also custom functions:

```{r}
# x-values and predictions based on doubled hp-values
hp_double <- function(x) 2 * x
ggpredict(mpg_model, "hp [hp_double]")
```

## Using values from a variable (vector)

```{r}
val <- c(100, 200, 300)
ggpredict(mpg_model, "hp [val]")
```

## Pretty value ranges

This section is intended to show some examples how the plotted output differs, depending on which value range is used. Some transformations, like polynomial or spline terms, but also quadratic or cubic terms, result in many predicted values. In such situation, predictions for some models lead to memory allocation problems. That is why `ggpredict()` "prettifies" certain value ranges by default, at least for some model types (like mixed models).

To see the difference in the "curvilinear" trend, we use a quadratic term on a standardized variable.

```{r}
library(sjmisc)
library(sjlabelled)
library(lme4)
data(efc)

efc$c12hour <- std(efc$c12hour)
efc$e15relat <- as_label(efc$e15relat)

m <- lmer(
  barthtot ~ c12hour + I(c12hour^2) + neg_c_7 + c160age + c172code + (1 | e15relat), 
  data = efc
)

me <- ggpredict(m, terms = "c12hour")
plot(me)
```

### Turn off "prettifying"

As said above, `ggpredict()` "prettifies" the vector, resulting in a smaller set of unique values. This is less memory consuming and may be needed especially for more complex models. 

You can turn off automatic "prettifying" by adding the `"all"`-shortcut to the `terms`-argument.

```{r}
me <- ggpredict(m, terms = "c12hour [all]")
plot(me)
```

This results in a smooth plot, as all values from the term of interest are taken into account.

### Using different ranges for prettifying

To modify the "prettifying", add the `"n"`-shortcut to the `terms`-argument. This allows you to select a feasible range of values that is smaller (and hence less memory consuming) them `"terms = ... [all]"`, but still produces smoother plots than the default prettyfing.

```{r}
me <- ggpredict(m, terms = "c12hour [n=2]")
plot(me)
```

```{r}
me <- ggpredict(m, terms = "c12hour [n=10]")
plot(me)
```

## Marginal effects conditioned on specific values of the covariates

By default, the `typical`-argument determines the function that will be applied to the covariates to hold these terms at constant values. By default, this is the mean-value, but other options (like median or mode) are possible as well. 

Use the `condition`-argument to define other values at which covariates should be held constant. `condition` requires a named vector, with the name indicating the covariate.

```{r}
data(mtcars)
mpg_model <- lm(mpg ~ log(hp) + disp, data = mtcars)

# "disp" is hold constant at its mean
ggpredict(mpg_model, "hp [exp]")

# "disp" is hold constant at value 200
ggpredict(mpg_model, "hp [exp]", condition = c(disp = 200))
```

## Marginal effects for each level of random effects

Marginal effects can also be calculated for each group level in mixed models. Simply add the name of the related random effects term to the `terms`-argument, and set `type = "re"`.

In the following example, we fit a linear mixed model and first simply plot the marginal effetcs, _not_ conditioned on random effects.

```{r}
library(sjlabelled)
library(lme4)
data(efc)
efc$e15relat <- as_label(efc$e15relat)
m <- lmer(neg_c_7 ~ c12hour + c160age + c161sex + (1 | e15relat), data = efc)
me <- ggpredict(m, terms = "c12hour")
plot(me)
```

Changing the type to `type = "re"` still returns population-level predictions by default. The major difference between `type = "fe"` and `type = "re"` is the uncertainty in the variance parameters. This leads to larger confidence intervals for marginal effects with `type = "re"`.

```{r}
me <- ggpredict(m, terms = "c12hour", type = "re")
plot(me)
```

To compute marginal effects for each grouping level, add the related random term to the `terms`-argument. In this case, confidence intervals are not calculated, but marginal effects are conditioned on each group level of the random effects.

```{r}
me <- ggpredict(m, terms = c("c12hour", "e15relat"), type = "re")
plot(me)
```

Marginal effects, conditioned on random effects, can also be calculated for specific levels only. Add the related values into brackets after the variable name in the `terms`-argument.

```{r}
me <- ggpredict(m, terms = c("c12hour", "e15relat [child,sibling]"), type = "re")
plot(me)
```

If the group factor has too many levels, you can also take a random sample of all possible levels and plot the marginal effects for this subsample of group levels. To do this, use `term = "<groupfactor> [sample=n]"`.

```{r}
data("sleepstudy")
m <- lmer(Reaction ~ Days + (1 + Days | Subject), data = sleepstudy)
me <- ggpredict(m, terms = c("Days", "Subject [sample=8]"), type = "re")
plot(me)
```
