rggplot2ggeffects

remove line and disconnect discrete points with ggeffects::plot(predict_response) and connect_lines


I'm using ggffects to plot predicted probabilities (options(ggeffects::ggeffects_margin = "marginalmeans")) of a multivariable GEE model with a binary predictor (coded as 1,2) modeled with geepack. I'm running into a new issue with some old code that I think was written under ggeffects version 1.5.0. I tried reinstalling that version without fixing the problem.

Is there a way to remove the line connecting discrete points on a plot?

Using this code



ggeffects::plot(
  predict_response(GEE model, terms = "x"),
  ci_style = "errorbar"
) +
  ggplot2::scale_x_continuous(
    labels = c("\n No",
               "\n Yes"),
    breaks = c(1, 2),
    expand = c(0,0)
  )

Produces this graph enter image description here

I want to remove the line connecting the dots

when I try to remove the line connecting the discrete points using the connect_lines argument, it does not remove it, and I get the same graph as above

ggeffects::plot(
  predict_response(GEE model, terms = "x"),
  ci_style = "errorbar",
  connect_lines = FALSE
) +
  ggplot2::scale_x_continuous(
    labels = c("\n No",
               "\n Yes"),
    breaks = c(1, 2),
    expand = c(0,0)
  )

[1] stringr_1.5.1   forcats_1.0.0   patchwork_1.2.0 ggeffects_1.7.2 [5] geepack_1.3.12  gtsummary_2.0.3 ggplot2_3.4.4   dplyr_1.1.4

I also opened an issue at Github https://github.com/strengejacke/ggeffects/issues/596


Solution

  • One of the nice things about ggplot2 is that a ggplot object is basically a large nested list which in most cases can be manipulated, i.e. in your case we can remove the geom_line layer which adds the connecting line.

    First, let's start with a minimal reproducible example of your issue based on the default example from geepack

    library(geepack)
    library(ggeffects)
    
    ### Example adapted from the geepack user guide
    n_cluster <- 6
    n_time <- 2
    set.seed(1213)
    timeorder <- rep(1:n_time, n_cluster)
    x <- timeorder
    idvar <- rep(1:n_cluster, each = n_time)
    uuu <- rep(rnorm(n_cluster), each = n_time) # A 'random intercept'
    yvar <- 1 + 2 * x + uuu + rnorm(length(x))
    simdat <- data.frame(idvar, timeorder, x, yvar)
    
    mod1 <- geeglm(yvar ~ x, id = idvar, data = simdat, corstr = "ar1")
    ###
    
    p <- plot(
      predict_response(mod1, terms = "x"),
      ci_style = "errorbar"
    ) +
      ggplot2::scale_x_continuous(
        labels = c(
          "\n No",
          "\n Yes"
        ),
        breaks = c(1, 2)
      )
    
    p
    

    Now, to remove the connecting line one can have a look at the layers which make up the plot:

    p$layers
    #> [[1]]
    #> mapping: group = ~.data[["group"]] 
    #> geom_line: na.rm = FALSE, orientation = NA
    #> stat_identity: na.rm = FALSE
    #> position_identity 
    #> 
    #> [[2]]
    #> geom_point: na.rm = FALSE
    #> stat_identity: na.rm = FALSE
    #> position_dodge 
    #> 
    #> [[3]]
    #> mapping: ymin = ~.data[["conf.low"]], ymax = ~.data[["conf.high"]], shape = NULL 
    #> geom_errorbar: na.rm = FALSE, orientation = NA, width = 0
    #> stat_identity: na.rm = FALSE
    #> position_dodge
    

    From this output we see that there are three layers and that the first is a geom_line and that there is only one geom_line. To drop this layer we can set it to NULL:

    p$layers[[1]] <- NULL
    
    p