Skip to content

Commit ef2598e

Browse files
committed
update packages
1 parent 596d870 commit ef2598e

File tree

1 file changed

+59
-43
lines changed

1 file changed

+59
-43
lines changed

packages.Rmd

+59-43
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,39 @@
11
# R Packages
22

3-
Here I will go into a bit of detail regarding <span class="pack">rstanarm</span> and <span class="pack">brms</span>. For standard models, these should be your first choice, rather than using Stan directly. Why? For one, the underlying code that is used will be more optimized and efficient than what you come up with, and has had multiple individuals developing that code and hundreds actually using it. Furthermore, you can still, and probably should, set your priors as you wish.
3+
Here I will go into a bit of detail regarding <span class="pack">rstanarm</span> and <span class="pack">brms</span>. For standard models, these should be your first choice, rather than using Stan directly. Why? For one, the underlying code that is used will be more optimized and efficient than what you come up with, and also, that code has had multiple individuals developing it and hundreds actually using it. Furthermore, you can still, and probably should, set your priors as you wish.
44

55
The nice thing about both is that you use the same syntax that you do for [R modeling](https://m-clark.github.io/R-models/) in general. Here is a a basic GLM in both.
66

77
```{r pack_demo, eval=FALSE}
8-
stan_glm(y ~ x + z, data=d)
9-
brm(y ~ x + z, data=d)
8+
stan_glm(y ~ x + z, data = d)
9+
10+
brm(y ~ x + z, data = d)
1011
```
1112

1213
And here are a couple complexities thrown in to show some minor differences. For example, the priors are specified a bit differently, and you may have options for one that you won't have in the other, but both will allow passing standard arguments, like cores, chains, etc. to <span class="pack">rstan</span>.
1314

1415
```{r pack_demo2, eval=FALSE}
15-
stan_glm(y ~ x + z + (1|g),
16-
data=d,
17-
family = binomial(link = "logit"),
18-
prior = normal(0, 1),
19-
prior_covariance = decov(regularization = 1, concentration = .5),
20-
QR = TRUE,
21-
chains = 2,
22-
cores = 2,
23-
iter = 2000)
24-
25-
brm(y ~ x + z + (1|g),
26-
data=d,
27-
family = bernoulli(link = 'logit'),
28-
prior = prior(normal(0, 1), class = b,
29-
cauchy(0, 5), class = sd),
30-
chains = 2,
31-
cores = 2,
32-
iter = 2000)
16+
stan_glm(
17+
y ~ x + z + (1|g),
18+
data = d,
19+
family = binomial(link = "logit"),
20+
prior = normal(0, 1),
21+
prior_covariance = decov(regularization = 1, concentration = .5),
22+
QR = TRUE,
23+
chains = 2,
24+
cores = 2,
25+
iter = 2000
26+
)
27+
28+
brm(
29+
y ~ x + z + (1|g),
30+
data = d,
31+
family = bernoulli(link = 'logit'),
32+
prior = prior(normal(0, 1), class = b, cauchy(0, 5), class = sd),
33+
chains = 2,
34+
cores = 2,
35+
iter = 2000
36+
)
3337
```
3438

3539
So the syntax is easy to use for both of them, and to a point identical to standard R modeling syntax, and both have the same <span class="pack">rstan</span> arguments. However, you'll need to know what's available to tweak and how to do so specifically for each package.
@@ -61,20 +65,22 @@ It's not a good thing that for the most common linear models R has multiple func
6165

6266
Contrast this with <span class="pack">brms</span>, which only requires the <span class="func">brm</span> function and appropriate family, e.g. 'poisson' or 'categorical', and which can do multinomial models also.
6367

64-
However, if you want to do a standard linear regression, I would not recommend using stan_lm, as it requires a prior for the $R^2$, which is unfamiliar and only explained in technical ways that are likely going to be lost on those less comfortable with or new to statistical or Bayesian analysis[^stan_lm_vignette]. The good news is that you can simply run stan_glm instead, and work with the prior on the regression coefficients as we have discussed, and you can use <span class="func">bayes_R2</span> to get the $R^2$.
68+
However, if you want to do a standard linear regression, I would probably not recommend using <span class="func">stan_lm</span>, as it requires a prior for the $R^2$, which is unfamiliar and only explained in technical ways that are likely going to be lost on those less comfortable with, or new to, statistical or Bayesian analysis[^stan_lm_vignette]. The good news is that you can simply run <span class="func">stan_glm</span> instead, and work with the prior on the regression coefficients as we have discussed, and you can use <span class="func">bayes_R2</span> to get the $R^2$.
69+
6570

71+
You can certainly use <span class="pack">brms</span> for GLM, but it would have to compile the code first, and so will always be relatively, but not prohibitively, slower. For linear models with interactions or GLM generally, you may prefer it for the marginal effects plots and other additional functionality.
6672

67-
You can certainly use <span class="pack">brms</span> for GLM, but it would have to compile the code and so will always be notably slower. For LM with interactions or GLM generally, you may prefer it for the marginal effects plots.
6873

6974

7075
## Categorical Models
7176

7277

73-
If you're just doing a standard logistic regression, I'd suggest <span class="func">stan_glm</span>, again, for the speed. In addition, it has a specific model function for conditional logistic regression (<span class="func">stan_clogit</span>). Beyond that, I'd probably recommend <span class="pack">brms</span>. For ordinal regression, <span class="func">stan_polr</span> goes back to requiring a prior for $R^2$, which is now the $R^2$ for the underlying latent variable of the ordinal outcome[^r2_polr]. Furthermore, <span class="pack">brms</span> has some ordinal-specific plots, as well as other types of ordinal regression (e.g. adjacent category) that allow the proportional odds assumption to be relaxed. It also can do multi-category models[^nomulti].
78+
If you're just doing a standard logistic regression, I'd suggest <span class="func">stan_glm</span>, again, for the speed. In addition, it has a specific model function for conditional logistic regression (<span class="func">stan_clogit</span>). Beyond that, I'd recommend <span class="pack">brms</span>. For ordinal regression, <span class="func">stan_polr</span> goes back to requiring a prior for $R^2$, which is now the $R^2$ for the underlying latent variable of the ordinal outcome[^r2_polr]. Furthermore, <span class="pack">brms</span> has some ordinal-specific plots, as well as other types of ordinal regression (e.g. adjacent category) that allow the proportional odds assumption to be relaxed. It also can do multi-category models.
7479

7580
```{r ordinal, eval=FALSE}
76-
brm(y ~ x, family='categorical') # nominal outcome with > 2 levels
77-
brm(y ~ cs(x), family='acat') # ordinal model with category-specific effects for x
81+
brm(y ~ x, family = 'categorical') # nominal outcome with > 2 levels
82+
83+
brm(y ~ cs(x), family = 'acat') # ordinal model with category-specific effects for x
7884
```
7985

8086
<span class="pack">brms</span> families for categorical:
@@ -110,31 +116,44 @@ The Bayesian approach really shines for mixed models in my opinion, where the ra
110116
- <span class="func">stan_mvmer</span>: multivariate outcome
111117
- <span class="func">stan_gamm4</span>: generalized additive mixed model in <span class="pack">lme4</span> style
112118

113-
I would probably just recommend <span class="pack">rstanarm</span> for stan_lmer and stan_glmer, as <span class="pack">brms</span> has more flexibility, and even would be recommended for the standard models if you want to estimate residual (co-)variance structure, e.g. autocorrelation. It also will do multivariate models, and one can use <span class="pack">mgcv</span>::<span class="func">s</span> for smooth terms in *any* <span class="pack">brms</span> model.
119+
I would probably just recommend <span class="pack">rstanarm</span> for stan_lmer and stan_glmer, as <span class="pack">brms</span> has more flexibility, and even would be recommended for the standard models if you want to estimate residual (co-)variance structure, e.g. autocorrelation. It also will do multivariate models, and one can use <span class="pack">mgcv</span>::<span class="func">s</span> for smooth terms in any <span class="pack">brms</span> model.
114120

115121

116122
## Other Models and Related
117123

118-
Along with all those <span class="pack">rstanarm</span> has specific functions for [beta regression](http://mc-stan.org/<span class="pack">rstanarm</span>/articles/betareg.html), [joint mixed/survival models](http://mc-stan.org/<span class="pack">rstanarm</span>/articles/jm.html), and [regularized linear regression](http://mc-stan.org/<span class="pack">rstanarm</span>/articles/lm.html). <span class="pack">brms</span> has many more distributional families, can do hypothesis testing[^], has marginal effects plots, and more. Both have plenty of tools for diagnostics, posterior predictive checks, and more of what has been discussed previously.
124+
Along with all those <span class="pack">rstanarm</span> has specific functions for [beta regression](http://mc-stan.org/rstanarm/articles/betareg.html), [joint mixed/survival models](http://mc-stan.org/rstanarm/articles/jm.html), and [regularized linear regression](http://mc-stan.org/rstanarm/articles/lm.html). <span class="pack">brms</span> has many more distributional families, can do hypothesis testing[^], has marginal effects plots, and more. Both have plenty of tools for diagnostics, posterior predictive checks, and more of what has been discussed previously.
119125

120-
In general, <span class="pack">rstanarm</span> is a great tool for translating your standard models into Bayesian ones in an efficient fashion. On the other hand, <span class="pack">brms</span> uses a simplified syntax and is notably more flexible. Here is a brief summary of my recommend use.
126+
In general, <span class="pack">rstanarm</span> is a great tool for translating your standard models into Bayesian ones in an efficient fashion. On the other hand, <span class="pack">brms</span> uses a simplified syntax and is notably more flexible. Here is a brief summary of my recommend use for common regression models.
121127

122128
```{r arm_brms_comparison, echo=FALSE}
123-
data_frame(Analysis = c('lm', 'glm', 'multinomial', 'ordinal', 'mixed', 'additive', 'regularized', 'beyond'),
124-
rstanarm = c('√', '√', '', '', '√', '√', '√', ''),
125-
brms = c('', '', '√', '√', '√', '√', '√', '√')) %>%
126-
kable(width='50%', align = 'lcc') %>%
127-
kable_styling(full_width = F)
129+
tibble(
130+
Analysis = c(
131+
'lm',
132+
'glm',
133+
'multinomial',
134+
'ordinal',
135+
'mixed',
136+
'additive',
137+
'regularized',
138+
'beyond'
139+
),
140+
rstanarm = c('√', '√', '', '', '√', '√', '√', ''),
141+
brms = c('', '', '√', '√', '√', '√', '√', '√')
142+
) %>%
143+
kable(width = '50%', align = 'lcc') %>%
144+
kable_styling(full_width = FALSE)
128145
```
129146

130-
Besides that, if you still need to model complexity not found within those, you can *still* use them to generate some highly optimized starter code, as they have functions for solely generating the underlying Stan code.
147+
Besides that, if you still need to model complexity not found within those, you can still use them to generate some highly optimized starter code, as they have functions for solely generating the underlying Stan code.
131148

132149

133150
## Even More Packages
134151

135-
I've focused on the two widely-used general-purpose packages, but nothing can stop Stan at this point. Here is a visualization of the current <span class="pack">rstan</span> ecosystem.
152+
I've focused on the two widely-used general-purpose packages, but nothing can stop Stan at this point. As of the latest update to this document, there are now `r length(devtools::revdep('rstan'))` other packages depending on <span class="pack">rstan</span> in some way. There are also interfaces for Python, Julia, and more. Odds are good you'll find one to suit your needs.
153+
154+
```{r stan_getgraph, eval=FALSE, echo=FALSE}
155+
# no longer works, and wasn't easily duplicated with e.g. devtools::revdep
136156
137-
```{r stan_getgraph, eval=TRUE, echo=FALSE}
138157
get_depgraph = function(pack) {
139158
require(httr)
140159
url = paste0('http://rdocumentation.org/api/packages/', pack, '/reversedependencies')
@@ -147,7 +166,7 @@ get_depgraph = function(pack) {
147166
stan_depgraph = get_depgraph('rstan')
148167
```
149168

150-
```{r stan_graph, echo=F, eval=T, cache=FALSE}
169+
```{r stan_graph, echo=F, eval=F, cache=FALSE}
151170
library(visNetwork)
152171
nodes = stan_depgraph$node_df %>%
153172
rename(label=name) %>%
@@ -175,11 +194,8 @@ visNetwork(nodes = nodes_trim,
175194
physics = T)
176195
```
177196

178-
At this point there are already a couple dozen packages working with Stan under the hood. Odds are good you'll find one to suit your needs.
179-
180197

181-
[^stan_lm_vignette]: The developers note in their vignette for <span class="func">stan_aov</span>:<br><br>'but it is reasonable to expect a researcher to have a plausible guess for R2 before conducting an ANOVA.'<br><br> Actually, I'm not sure how reasonable this is. I see many, many researchers of varying levels of expertise, and I don't think any of them would be able to hazard much of a guess about $R^2$ before running a model, unless they're essentially duplicating previous work. I also haven't come across an explanation in the documentation (which is otherwise great) of how to specify it that would be very helpful to people just starting out with Bayesian analysis or even statistics in general. If the result is that one then has to try a bunch of different priors, then that becomes the focus of the analytical effort, which likely won't appeal to people just wanting to run a standard regression model.
182198

183-
[^r2_polr]: If someone tells me they know what the prior should be for that, I probably would not believe them.
199+
[^stan_lm_vignette]: The developers note in their [vignette for ANOVA](https://cran.r-project.org/web/packages/rstanarm/vignettes/aov.html):<br><br>'but it is reasonable to expect a researcher to have a plausible guess for R2 before conducting an ANOVA.'<br><br> Actually, I'm not sure how reasonable this is. In consulting I've seen many, many researchers of varying levels of expertise, and I don't think even a large minority of them would be able to hazard much of a guess about $R^2$ before running a model, unless they're essentially duplicating previous work. I also haven't come across an explanation in the documentation (which is otherwise great) of how to specify it that would be very helpful to people just starting out with Bayesian analysis or even statistics in general. If the result is that one then has to try a bunch of different priors, then that becomes the focus of the analytical effort, which likely won't appeal to people just wanting to run a standard regression model.
184200

185-
[^nomulti]: The corresponding distribution is the categorical distribution, which is a multinomial distribution with size = 1. Multinomial count models, i.e. with size > 1, on the other hand, are not currently supported [except indirectly](https://github.com/paul-buerkner/brms/issues/338). However, the multinomial-poisson transformation can be used instead.
201+
[^r2_polr]: If someone tells me they know what the prior should be for that, I probably would not believe them.

0 commit comments

Comments
 (0)