Katie Tetzloff
Katie Tetzloff

Reputation: 65

Can you change the shape of the points in ggeffects or Sjplot?

I can't figure out how to change the shape of the points in sjplot or ggeffects - I have

in sJplot:

p<-plot_model(my.lm, type = "pred", terms = c("Var1", "Var2", "Var3"))

This makes the points of Var 2 different colors, but I need them to be different shapes.

I can use ggeffects for this, but I still can't figure out how to make an equivalent graph to plot_model in sJplot with different point shapes.

g<-ggpredict(my.lm, terms=c("Var1","Var2", "Var3"))

Thank you

Upvotes: 0

Views: 992

Answers (1)

chemdork123
chemdork123

Reputation: 13843

There doesn't seem to be a simple way to do this (like an argument within plot_model()). So, it seems the only option here is the "nuclear option" - which is changing the values in the $data layer of the plot object. It gets a bit "hacky", but it does work.

I'll demonstrate based on an adaptation of an example in this vignette here.

library(ggplot2)
library(sjPlot)
library(sjmisc)
library(sjlabelled)

data(efc)
y <- ifelse(efc$neg_c_7 < median(na.omit(efc$neg_c_7)), 0, 1)
df <- data.frame(
  y = to_factor(y),
  sex = to_factor(efc$c161sex),
  dep = to_factor(efc$e42dep),
  barthel = efc$barthtot,
  education = to_factor(efc$c172code)
)

set_label(df$y) <- "High Negative Impact"
fit <- glm(y ~., data = df, family = binomial(link = "logit"))

p <- plot_model(fit, colors = "black")
p

enter image description here

Our goal is to change the shape of those points to something else. First step is to use ggplot_build() to pull the information from the object we just created, p.

qq <- ggplot_build(p)

The object, qq, is a list containing 3 layers: data, layout, and plot. Herein, we want to change the information contained in qq$data, which has the aesthetics after they have been mapped. qq$data is a list itself, containing 3 tables. Each of these tables corresponds to a particular geom in the underlying ggplot2 call. The first table qq$data[[1]], is for the vline geom. The third table qq$data[[3]] is for all the line segments behind the points (you'll note they have xmin, xmax, ymin, and ymax columns). The second table is the one we want, which is for the point geoms:

> qq$data[[2]]
  colour  fill x           y PANEL group shape size alpha stroke
1  black black 7  0.28191638     1     7    19  2.5    NA    0.5
2  black black 6  0.21074532     1     6    19  2.5    NA    0.5
3  black black 5  0.48863767     1     5    19  2.5    NA    0.5
4  black black 4  0.39529220     1     4    19  2.5    NA    0.5
5  black black 3 -0.01294270     1     1    19  2.5    NA    0.5
6  black black 2  0.09837842     1     3    19  2.5    NA    0.5
7  black black 1  0.12316583     1     2    19  2.5    NA    0.5

You can see all points are made with shape=19. We can change that, then rebuild the plot from our modified qq object like so:

qq$data[[2]]$shape <- 5
plot(ggplot_gtable(qq))

enter image description here

We can do fun things like change all sorts of stuff manually in the plot if you want:

qq$data[[1]]$colour <- "blue"     # change color of vertical line
qq$data[[2]]$shape[3:5] <- 19     # points 3-5 are now circles again
qq$data[[2]]$color[4:7] <- "red"  # last 4 point are red
qq$data[[2]]$size[c(2,4,6)] <- 4  # some points are bigger

plot(ggplot_gtable(qq))

enter image description here

A word on saving these files plots to file, if you like to use ggsave(...): You cannot save the output of plot(ggplot_gtable(qq)) directly using ggsave(), since the default value for plot= in ggsave() is last_plot(), which does not work here when using plot(...). Therefore if you want to save with ggsave(), you can do the following:

p <- ggplot_gtable(qq)       # save to a large gtable
ggsave("name.png", plot = p  # reference the gtable object

Upvotes: 2

Related Questions