Differences between by-factor smooths in brms


I am fitting splines in brms, and I am wondering how I can plot the smooth of the difference between two individual smooths in a binary by-factor smooth (the difference smooth). This is very easy to do using mgcv, but I’m not sure how to get the same results (and plots) with brms. I’m also wondering how to interpret the brms output with a by-factor smooth when I use an ordered binary factor.

Here’s an example of what I am trying (using the mtcars dataset)

mtcars$vs ← as.ordered(mtcars$vs)
brms_mod ← brm(mpg ~ s(hp) + vs + s(hp, by=vs), data = mtcars)
gam_mod ← gam(mpg ~ s(hp) + vs + s(hp, by=vs), data = mtcars)

As I understand it in mgcv, if I use an ordered factor in a by-factor smooth, the model will produce the difference in the smooth between two categories of the factor (if it’s binary). I assume this would be the same in brms, but the output looks a bit different, so I’m not 100% sure.

Here is the output from the brms model above (brms_mod):

And here is the screenshot from the mgcv model (gam_mod):

From what I understand for splines in brms models, the sds() parameters for the smooth terms are the estimates of the “wiggliness”. With an ordered factor in brms, would the term “sds(shpvs1_1)” represent the wiggliness of the difference smooth? In the mgcv model, I would interpret the term s(hp):vs1 as the estimate of the difference smooth. This term in the mgcv model has an EDF of 1, so there’s no wiggliness in the difference smooth.

I would also like to be able to plot the difference between two smooths. With an ordered binary factor, mgcv produces this automatically. For the mgcv model above, I can obtain this plot from the mgcv model above with plot(gam_mod):

When I use conditional_effects(brms_mod, “hp:vs”) to obtain the smooth plots from the brms model , I obtain each smooth within each factor level on the same plot. Here is what I get:

This plot is very helpful for visualizing the results, but I would also like to see the difference smooth (with intervals) from brms. Is there a way to obtain that with conditional_effects()?

Thank you!

1 Like

sorry for not getting to your question earlier. It is relevant and well written.

I don’t think what you aim for is directly supported, but note that conditional_effects really just computes posterior predictions of the model (by default with posterior_predict) while changing only the smooth predictor (here hp). So what you are getting is AFAIK not the difference of the smooth themselves, but the difference of the whole predictions.

With that in mind, you can use posterior_predict (or posterior_epred if you want to work without the measurement noise) to predict the values for two sets of conditions, differring only in the vs value, then, for each sample, compute the difference and summarise this in a plot. (note that this will also include the fixed vs effect). I don’t think there is an

A similar question has been discussed at Extracting posterior samples of smooth effects in brms, so linking for completeness.

I think there was some work in tidybayes to let you extract the smooth terms separately (Add support for mgcv · Issue #130 · mjskay/tidybayes · GitHub) but it doesn’t seem to have been finalized (tagging @mjskay for confirmation)

Does that make sense?

Best of luck with your model!

P.S.: Note that you can use triple backticks (```) to format text as code / output.


Thank you for the helpful reply! I will look into these techniques the prior posts regarding smooths.

I did, however, appear to have found what I was looking for in terms of obtaining the difference smooth in brms that I was getting in mgcv, and it’s more straightforward than I thought. If I take the same brms model I displayed in my first post but use conditional_smooths(brms_mod) instead of conditional_effects(brms_mod), I obtain the smooth of the base category (vs = 0) and the difference smooth between vs = 0 and vs = 1. I’m now wondering what the exactly the difference between conditional_smooths and conditional_effects is. I’ve tried to do some reading on this, but I don’t think I’m quite understanding the difference besides conditional_smooths plots the smooth term (although, conditional_effects appears to do that as well). The plot that mgcv produces appears to be nearly identical to what I obtain with conditional_smooths, so it seems that conditional_effects wasn’t producing what I was looking for in the first place. Any further guidance/input is greatly appreciated.


1 Like

Honestly, I am not sure - the documentation is not exactly clear and I couldn’t understand the code completely. What I am sure, is that conditional_effects will take into account all other predictors (assuming they are at they mean / reference values if you don’t specify anything). It is thus possible that conditional_smooths either doesn’t do that or does that differently… But really, not completely sure.