-
Notifications
You must be signed in to change notification settings - Fork 41
/
Copy pathREADME.rmd
219 lines (144 loc) · 16.3 KB
/
README.rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
---
output:
github_document:
toc: false
fig_width: 7
fig_height: 5
vignette: >
%\VignetteIndexEntry{README}
\usepackage[utf8]{inputenc}
%\VignetteEngine{knitr::rmarkdown}
bibliography: paper/paper.bib
editor_options:
chunk_output_type: console
---
```{r, echo = FALSE, warning=FALSE, message=FALSE}
options(digits = 2)
knitr::opts_chunk$set(
collapse = TRUE,
fig.path = "man/figures/",
fig.width = 7,
fig.height = 5,
comment = "#>",
dev = "png"
)
# supported via name space
ggeffects_namespace <- ls(getNamespace("ggeffects"))
ns_get_predictions <- ggeffects_namespace[grepl("^get_predictions\\.", ggeffects_namespace)]
.supported_models <- gsub("^get_predictions\\.", "", ns_get_predictions)
.supported_models <- setdiff(unique(sort(c(.supported_models,
"wblm", "wbm", "phylolm", "phyloglm", "mblogit", "mclogit", "logitr", "averaging",
"orm", "mlogit", "glimML", "cgam", "ols", "mixor", "glmx", "lrm", "lmrob", "feglm",
"glmrob", "glmRob", "brglm", "bigglm", "biglm", "speedglm", "speedlm", "svyglm.nb",
"svyglm", "stanreg", "brmsfit", "bayesx", "gamlss", "bamlss", "gam", "tobit",
"survreg", "Gam", "MCMCglmm", "glmerMod", "glmmTMB", "nlmerMod", "lmerMod",
"merModLmerTest", "rlmerMod", "lme", "logistf", "ivreg", "fixest", "gls", "geeglm",
"clmm", "clm", "clm2", "polr", "rq", "rqss", "gee", "plm", "negbin", "vgam", "vglm",
"lm_robust", "lmrob", "lmRob", "betareg", "truncreg", "coxph", "brmultinom",
"multinom", "bracl", "Zelig-relogit", "zerotrunc", "zeroinfl", "hurdle", "MixMod",
"glm", "lm", "tidymodels", "betabin", "bglmer", "blmer", "cgamm", "gamm", "gamm4",
"glm.nb", "polr", "rlm", "rqs", "glmer.nb", "glmmPQL", "nestedLogit", "sdmTMB",
"flic", "flac", "glmgee", "glm_weightit", "multinom_weightit", "ordinal_weightit"
))), "default")
```
# ggeffects - Estimated Marginal Means and Adjusted Predictions from Regression Models<img src="man/figures/logo.png" align="right" />
[](https://doi.org/10.21105/joss.00772) [](https://strengejacke.github.io/ggeffects/) [](https://cranlogs.r-pkg.org/) [](https://cranlogs.r-pkg.org/)
Lüdecke D (2018). _ggeffects: Tidy Data Frames of Marginal Effects from Regression Models._ Journal of Open Source Software, 3(26), 772. doi: [10.21105/joss.00772](https://doi.org/10.21105/joss.00772)
## Maintenance mode
_Package **ggeffects** is in maintenance mode and will be superseded by the [**modelbased-package**](https://easystats.github.io/modelbased/) from the [easystats-project](https://easystats.github.io/easystats/)._
_The main reason is to reduce double maintenance burden for me. We have largely revised the **modelbased** package, adding many new features, revising the plotting capabilities, and last not least we added full support for the **marginaleffects** package as (defaul) backend for estimating marginal means, effects and contrasts._
_**ggeffects**, which has a pretty stable `predict_response()` function to calculate adjusted predictions for many, many models, and which has very matured plotting capabilities, lately got a `test_prediction()` function to calculate contrasts and pairwise comparisons, too, also built on top of **marginaleffects**. Effectively, there are now two packages I'm involved with very similar tasks and functionality. However, **marginaleffects** is undergoing substantial changes right now, meaning I had to re-write a lot of code in `test_predictions()` to make it work again (`test_predictions()` is still available, relying on the **emmeans** package, and hence no longer that feature-rich as it was before). Therefore, I decided to remove all functionality that relied on **marginaleffects**, and focussing on **modelbased** instead, to reduce maintenance burden for me._
_**modelbased** is easier to maintain, because it was written lateley, with more package development experience on our side. Furthermore, it has a clear and intuitive user interface and is pretty stable and finished right now. It also offers some features that **ggeffects** has not included, like estimating marginal effects (and not only adjusted predictions or marginal means). Thus, future development of new features will happen in **modelbased**. **ggeffects** will still be maintained, i.e. bugs will be fixed if possible, and maybe smaller new features will be added._
_Your code using functions like `predict_response()`, `ggpredict()` or `plot()` will still work, will still work in the future and there will be no limitations regarding functionality for those functions! If you only used these functions, there is no reason to worry or to change anything! However, to leverage the full power of predictions, including contrasts and pairwise comparisons or calculating marginal effects, the recommendation is to switch to [**modelbased-package**](https://easystats.github.io/modelbased/)!_
## Why do we need (marginal/conditional) effects or (adjusted) predicted values?
After fitting a model, it is useful generate model-based estimates (expected values, or _adjusted predictions_) of the response variable for different combinations of predictor values. Such estimates can be used to make inferences about relationships between variables - adjusted predictions tell you: what is the expected ouctome for certain values or levels of my predictors?
_Adjusted predictions_ or _marginal means_ are often easier to understand than raw regression coefficients. In particular, their visualization allows to intuitively get the idea of how predictors and outcome are associated, even for complex models.
## Aims of this package
**ggeffects** is a light-weight package that aims at easily calculating adjusted predictions and estimated marginal means at meaningful values of covariates from statistical models. Furthermore, it is possible to compute contrasts or pairwise comparisons, to test predictions and differences in predictions for statistical significance. Finally, you can easily produce nice figures to visualize the results.
What you basically would need for your workflow is:
- `predict_response()` (understand your results)
- `test_predictions()` (check for "significant" results)
- `plot()` (communicate your results)
Three core ideas describe the philosophy of the function design and help users to achieve the above mentioned goals:
1) Functions are type-safe and always return a data frame with the same, consistent structure;
2) there is a simple, unique approach to calculate adjusted predictions and estimated marginal means for many different models;
3) the package supports "labelled data" [@daniel_ludecke_2018_1249216], which allows human readable annotations for graphical outputs.
This means, users do not need to care about any expensive steps after modeling to visualize the results. The returned as data frame is ready to use with the **ggplot2**-package, however, there is also a `plot()`-method to easily create publication-ready figures.
Adjusted predictions or estimated marginal means are always calculated on the *response* scale, which is the easiest and most intuitive scale to interpret the results.
It is easy to start, you just need one function: `predict_response()`, and two arguments: the model and the "focal terms", i.e. the predictors that you are mainly interested in. Examples are shown below.
## So, when do I need the *ggeffects* package?
You should use *ggeffects*...
- ... when you want to understand how predictors and outcome are related, no matter whether you have simple or complex models, interaction or transformed terms. See how to start [in this vignette](https://strengejacke.github.io/ggeffects/articles/ggeffects.html). The syntax for the *ggeffects* functions is super easy and consistent across the different type of models and complexity.
- ... when you want to perform pairwise comparisons, in order to see whether there are statistically significant differences in the association of, for instance, different groups or categories of your predictors and your outcome ("effects", or sometimes "marginal effects").
- ... when you need impressive figures instead of long, confusing tables to describe your results. There are several examples in the [documentation](https://strengejacke.github.io/ggeffects/), for example [this vignette](https://strengejacke.github.io/ggeffects/articles/introduction_plotmethod.html).
- ... and even when you want to check, whether your model appropriately describes your data. See [this vignette](https://strengejacke.github.io/ggeffects/articles/introduction_partial_residuals.html) to learn more about how to use *ggeffects* for model diagnostics.
A workflow in R would then include using following functions in this order: `predict_response()`, `plot()`, and `test_predictions()` - that's all you need! See also [this example workflow](https://strengejacke.github.io/ggeffects/articles/practical_glm_workflow.html) using logistic regression.
## Installation
[](https://cran.r-project.org/package=ggeffects) [](https://strengejacke.r-universe.dev)
Type | Source | Command
---|---|---
Release | CRAN | `install.packages("ggeffects")`
Development | r - universe | `install.packages("ggeffects", repos = "https://strengejacke.r-universe.dev")`
Development | GitHub | `remotes::install_github("strengejacke/ggeffects")`
Or you can run [`ggeffects::install_latest()`](https://strengejacke.github.io/ggeffects/reference/install_latest.html) to install the latest development version from r-universe.
## Adjusted predictions at...: marginalizing over non-focal predictors
`predict_response()` is a wrapper around three "workhorse" functions, `ggpredict()`, `ggemmeans()` and `ggaverage()`. Depending on the value of the `margin` argument, `predict_response()` calls one of those functions, with different arguments. It's important to note that:
1. Predictions are always returned on the *response scale*, no matter which model is used. This is the most intuitive scale to interpret your results (the predicted values).
2. The response is predicted at the values or levels of your *focal terms*, i.e. you specify the predictors you are mainly interested in, using the `terms` argument. The predicted values are calculated for these values, while all other predictors are marginalized over.
The `margin` argument in `predict_response()` indicates how to marginalize over the *non-focal* predictors, i.e. those variables that are *not* specified in `terms`. Each option answers slightly different questions. Possible values are:
- `"mean_reference"` and `"mean_mode"`: `"mean_reference"` calls `ggpredict()`, i.e. non-focal predictors are set to their mean (numeric variables), reference level (factors), or "most common" value (mode) in case of character vectors. `"mean_mode"` calls `ggpredict(typical = c(numeric = "mean", factor = "mode"))`, i.e. non-focal predictors are set to their mean (numeric variables) or mode (factors, or "most common" value in case of character vectors).
Question answered: "What is the predicted (or: expected) value of the response at meaningful values or levels of my focal terms for a 'typical' observation in my data?", where 'typical' refers to certain characteristics of the remaining predictors.
- `"marginalmeans"`: calls `ggemmeans()`, i.e. non-focal predictors are set to their mean (numeric variables) or marginalized over the levels or "values" for factors and character vectors. Marginalizing over the factor levels of non-focal terms computes a kind of "weighted average" for the values at which these terms are hold constant. There are different weighting options that can be chosen with the `weights` argument.
Question answered: "What is the predicted (or: expected) value of the response at meaningful values or levels of my focal terms for an 'average' observation in my data?". It refers to randomly picking a subject of your sample and the result you get on average.
- `"empirical"` (or on of its aliases, `"counterfactual"` or `"average"`): calls `ggaverage()`, i.e. non-focal predictors are marginalized over the observations in your sample. The response is predicted for each subject in the data and predicted values are then averaged across all subjects, aggregated/grouped by the focal terms. Averaging is applied to "counterfactual" predictions [@dickerman_counterfactual_2020]. There is a more detailed description in [this vignette](https://strengejacke.github.io/ggeffects/articles/technical_differencepredictemmeans.html).
Question answered: "What is the predicted (or: expected) value of the response at meaningful values or levels of my focal terms for the 'average' observation in the population?". It does not only refer to the actual data in your sample, but also "what would be if" we had more data, or if we had data from a different population.
## Documentation and Support
Please visit [https://strengejacke.github.io/ggeffects/](https://strengejacke.github.io/ggeffects/) for documentation and vignettes. For questions about the functionality, you may either contact me via email or also file an issue.
## ggeffects supports many different models and is easy to use
Adjusted predictions can be calculated for many different models. Currently supported model-objects are: `r toString(.supported_models)`.
Support for models varies by marginalization method (the `margin` argument), i.e. although `predict_response()` supports most models, some models are only supported exclusively by one of the four downstream functions (`ggpredict()`, `ggemmeans()`, `ggeffect()` or `ggaverage()`). This means that not all models work for every `margin` option of `predict_response()`. Other models not listed here might work as well, but are currently not tested.
Interaction terms, splines and polynomial terms are also supported. There is a generic `plot()`-method to plot the results using **ggplot2**.
## Examples
The returned data frames always have the same, consistent structure and column names, so it's easy to create ggplot-plots without the need to re-write the function call. `x` and `predicted` are the values for the x- and y-axis. `conf.low` and `conf.high` could be used as `ymin` and `ymax` aesthetics for ribbons to add confidence bands to the plot. `group` can be used as grouping-aesthetics, or for faceting.
`predict_response()` requires at least one, but not more than four terms specified in the `terms`-argument. Predicted values of the response, along the values of the first term are calculated, optionally grouped by the other terms specified in `terms`.
### Adjusted predictions for one focal predictor
```{r message=FALSE, warning=FALSE}
library(ggeffects)
library(splines)
library(datawizard)
data(efc, package = "ggeffects")
efc <- to_factor(efc, c("c161sex", "e42dep"))
fit <- lm(barthtot ~ c12hour + bs(neg_c_7) * c161sex + e42dep, data = efc)
predict_response(fit, terms = "c12hour")
```
A possible call to ggplot could look like this:
```{r message=FALSE, warning=FALSE}
library(ggplot2)
mydf <- predict_response(fit, terms = "c12hour")
ggplot(mydf, aes(x, predicted)) +
geom_line() +
geom_ribbon(aes(ymin = conf.low, ymax = conf.high), alpha = 0.1)
```
However, there is also a `plot()`-method. This method uses convenient defaults, to easily create the most suitable plot for the predictions.
```{r message=FALSE, warning=FALSE}
mydf <- predict_response(fit, terms = "c12hour")
plot(mydf)
```
### Adjusted predictions for several focal predictors
With three variables, predictions can be grouped and faceted.
```{r message=FALSE, warning=FALSE}
result <- predict_response(fit, terms = c("neg_c_7", "c161sex", "e42dep"))
# we want a more compact table, thus we use `print()` explicitly
print(result, collapse_table = TRUE, collapse_ci = TRUE)
ggplot(result, aes(x = x, y = predicted, colour = group)) +
geom_line() +
facet_wrap(~facet)
```
`plot()` works for this case, as well:
```{r message=FALSE, warning=FALSE}
plot(result)
```
## Citation
In case you want / have to cite my package, please use `citation('ggeffects')` for citation information:
Lüdecke D (2018). _ggeffects: Tidy Data Frames of Marginal Effects from Regression Models._ Journal of Open Source Software, 3(26), 772. doi: [10.21105/joss.00772](https://doi.org/10.21105/joss.00772)
## References