rggplot2visualizationfacet-wrapsjplot

Facet breaks either sjPlot or geom_point


I am trying to produce with faceted sjPlot lines, and geom_points. mtcars data supplied as an example.

fit <- lm(mpg ~ cyl * hp * am, data = mtcars)

I want to have slopes of mpg by hp for each cyl, across two panels (one for each value of am). This combination makes more sense with my real data! The following code facets sjPlot but not geom_point (the geom_points shown are identical between the two faceted panels):

plot_model(fit, type = "pred", terms = c("hp", "cyl", "am")) +
  geom_point(data = mtcars,
             aes(x = hp, y = mpg, colour = cyl), 
             inherit.aes = FALSE, size = 0.5)

no_zigzags.png

Adding + facet_wrap( ~ am) makes the geom_point values facet correctly (they are different between the two panels), but sjPlot now draws a line that zig zags from point to point.

zigzags.png

Data

> str(mtcars)

tibble [32 × 11] (S3: tbl_df/tbl/data.frame)
 $ mpg : num [1:32] 21 21 22.8 21.4 18.7 18.1 14.3 24.4 ...
 $ cyl : Factor w/ 3 levels "4","6","8": 2 2 1 2 3 2 3 1  ...
 $ disp: num [1:32] 160 160 108 258 360 ...
 $ hp  : num [1:32] 110 110 93 110 175 105 245 62 ...
 $ drat: num [1:32] 3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 ...
 $ wt  : num [1:32] 2.62 2.88 2.32 3.21  ...
 $ qsec: num [1:32] 16.5 17 18.6 19.4 ...
 $ vs  : num [1:32] 0 0 1 1 0 1 0 1 ...
 $ am  : Factor w/ 2 levels "0","1": 2 2 2 1 1 1 1  ...
 $ gear: num [1:32] 4 4 4 3 3 3 3 4 ...
 $ carb: num [1:32] 4 4 1 1 2 1 4 2 ...
pred_dat <- sjPlot::get_model_data(
  fit,
  type  = "pred",
  terms = c("hp", "cyl", "am"))

levels(pred_dat$facet) # pred_dat$facet to see what plot_model facets on

[1] "0" "1" # noting that the facet levels are identical to mtcars$am.

Solution

  • Have you tried using show.data = TRUE in the sjPlot call? E.g.

    library(tidyverse)
    library(sjPlot)
    
    mtcars$cyl <- factor(mtcars$cyl)
    mtcars$am <- factor(mtcars$am, labels = c("AM = 0", "AM = 1"))
    
    fit <- lm(mpg ~ cyl * hp * am, data = mtcars)
    
    plot_model(fit, type = "pred", terms = c("hp", "cyl", "am"),
               show.data = TRUE, jitter = 0.01)
    

    example

    Created on 2025-12-09 with reprex v2.1.1

    Not sure if this is what you're looking for, but I wasn't able to figure out a solution with geom_point() and facet_wrap() - hope it helps!