rmixed-models

Plot mixed-effects model with binary predictor and binary response variable


I'm looking for a pleasing and informative way to visualize a mixed-model where the response variable and the predictor variable are both binary.

m_0 <- glmer(Preselected_0 ~ N_G_altnt_Q_YN + (N_G_altnt_Q_YN | File / Person_anon), family = "binomial", 
                    data = df)

The plot I get from using plot_model is this:

library(sjPlot)

plot_model(m_0, type = "eff", terms = c("N_G_altnt_Q_YN"), #pred.type = "fe", ci.lvl = .68, line.size = 1.2,
           title = ""
)

enter image description here

The kind of plot I'd like to get is this: Or, if that's not possible or advisable with the binary predictor, some other viz that is more visually appealing and informative -- any help is appreciated!

enter image description here

Data:

df <- structure(list(N_G_altnt_Q_YN = structure(c(1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 2L, 1L, 2L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 
1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 
2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 
1L, 2L, 1L, 2L, 1L, 2L, 2L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 2L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 
1L, 1L, 2L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 
1L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 2L, 2L, 2L, 2L, 1L, 2L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
2L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 2L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 
1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 2L), levels = c("0", "1"), class = "factor"), 
    Preselected_0 = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 2L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 2L, 2L, 
    2L, 2L, 2L, 1L, 1L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 2L, 1L, 
    2L, 1L, 1L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 2L, 1L, 2L, 2L, 2L, 2L, 2L, 1L, 2L, 1L, 1L, 2L, 2L, 
    2L, 1L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 
    2L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 2L, 1L, 1L, 1L, 1L, 
    2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 
    2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 2L, 
    1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 1L, 2L, 1L, 1L, 1L, 1L, 2L, 
    2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 
    1L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 2L, 1L, 
    2L, 1L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 1L, 2L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L), levels = c("YES", "NO"
    ), class = "factor"), File = c("F01", "F01", "F01", "F01", 
    "F01", "F01", "F01", "F01", "F01", "F01", "F01", "F01", "F01", 
    "F01", "F01", "F01", "F01", "F01", "F01", "F01", "F01", "F01", 
    "F01", "F01", "F01", "F01", "F04", "F04", "F04", "F04", "F04", 
    "F04", "F04", "F04", "F04", "F04", "F04", "F04", "F04", "F04", 
    "F04", "F04", "F04", "F04", "F04", "F04", "F04", "F04", "F04", 
    "F04", "F04", "F04", "F04", "F04", "F04", "F04", "F04", "F04", 
    "F04", "F04", "F04", "F04", "F04", "F04", "F04", "F04", "F04", 
    "F04", "F04", "F04", "F04", "F04", "F04", "F04", "F04", "F04", 
    "F04", "F04", "F04", "F04", "F04", "F04", "F04", "F04", "F04", 
    "F04", "F04", "F04", "F04", "F04", "F07", "F07", "F07", "F07", 
    "F07", "F07", "F07", "F07", "F07", "F07", "F07", "F07", "F07", 
    "F07", "F07", "F07", "F07", "F07", "F07", "F07", "F07", "F07", 
    "F07", "F07", "F07", "F07", "F07", "F07", "F07", "F07", "F07", 
    "F07", "F07", "F07", "F07", "F07", "F07", "F07", "F07", "F07", 
    "F07", "F07", "F07", "F07", "F07", "F07", "F07", "F07", "F07", 
    "F07", "F07", "F07", "F07", "F08", "F08", "F08", "F08", "F08", 
    "F08", "F08", "F08", "F08", "F08", "F08", "F08", "F08", "F08", 
    "F08", "F08", "F08", "F08", "F08", "F08", "F08", "F08", "F08", 
    "F08", "F08", "F08", "F08", "F08", "F08", "F08", "F08", "F08", 
    "F08", "F08", "F08", "F08", "F08", "F08", "F08", "F12", "F12", 
    "F12", "F12", "F12", "F12", "F12", "F12", "F12", "F12", "F12", 
    "F12", "F12", "F12", "F12", "F12", "F12", "F12", "F12", "F12", 
    "F12", "F12", "F12", "F12", "F12", "F12", "F12", "F12", "F16", 
    "F16", "F16", "F16", "F16", "F16", "F16", "F16", "F16", "F16", 
    "F16", "F16", "F16", "F16", "F16", "F16", "F16", "F16", "F16", 
    "F18", "F18", "F18", "F18", "F18", "F18", "F18", "F18", "F18", 
    "F18", "F18", "F18", "F18", "F18", "F18", "F18", "F18", "F18", 
    "F18", "F18", "F18", "F18", "F18", "F20", "F20", "F20", "F20", 
    "F20", "F20", "F20", "F20", "F20", "F20", "F20", "F20", "F20", 
    "F20", "F20", "F20", "F20", "F20", "F20", "F22", "F22", "F22", 
    "F22", "F22", "F22", "F22", "F22", "F22", "F22", "F23", "F23", 
    "F23", "F23", "F23", "F23", "F23", "F23", "F23", "F23", "F23", 
    "F23", "F23", "F23", "F23", "F23", "F23", "F23", "F23", "F23", 
    "F23", "F23", "F23", "F23", "F23", "F23", "F23", "F23", "F23", 
    "F23", "F23", "F23", "F23", "F23", "F23", "F23", "F23", "F23", 
    "F23", "F19", "F19", "F19", "F19", "F19", "F19", "F19", "F19", 
    "F19", "F19", "F19", "F16"), Person_anon = c("GGGGGGGGGGGGGGGl", 
    "IIIIIIIIIIIIt", "IIIIIIIIIIIIt", "IIIIIIIIIIIIt", "IIIIIIIIIIIIt", 
    "IIIIIIIIIIIIt", "IIIIIIIIIIIIt", "GGGGGGGGGGGGGGGl", "IIIIIIIIIIIIt", 
    "IIIIIIIIIIIIt", "KKKKKKKKKKr", "IIIIIIIIIIIIt", "KKKKKKKKKKr", 
    "IIIIIIIIIIIIt", "IIIIIIIIIIIIt", "IIIIIIIIIIIIt", "GGGGGGGGGGGGGGGl", 
    "IIIIIIIIIIIIt", "IIIIIIIIIIIIt", "KKKKKKKKKKr", "IIIIIIIIIIIIt", 
    "IIIIIIIIIIIIt", "IIIIIIIIIIIIt", "IIIIIIIIIIIIt", "IIIIIIIIIIIIt", 
    "IIIIIIIIIIIIt", "DDDDDDDDDDDDe", "AAAAAAAAAAAAAn", "DDDDDDDDDDDDe", 
    "DDDDDDDDDDDDe", "DDDDDDDDDDDDe", "DDDDDDDDDDDDe", "DDDDDDDDDDDDe", 
    "DDDDDDDDDDDDe", "DDDDDDDDDDDDe", "CCCCCCCCCCx", "CCCCCCCCCCx", 
    "DDDDDDDDDDDDe", "DDDDDDDDDDDDe", "DDDDDDDDDDDDe", "DDDDDDDDDDDDe", 
    "DDDDDDDDDDDDe", "AAAAAAAAAAAAAn", "DDDDDDDDDDDDe", "CCCCCCCCCCx", 
    "CCCCCCCCCCx", "CCCCCCCCCCx", "AAAAAAAAAAAAAn", "AAAAAAAAAAAAAn", 
    "AAAAAAAAAAAAAn", "DDDDDDDDDDDDe", "DDDDDDDDDDDDe", "AAAAAAAAAAAAAn", 
    "DDDDDDDDDDDDe", "CCCCCCCCCCx", "DDDDDDDDDDDDe", "DDDDDDDDDDDDe", 
    "AAAAAAAAAAAAAn", "AAAAAAAAAAAAAn", "CCCCCCCCCCx", "DDDDDDDDDDDDe", 
    "AAAAAAAAAAAAAn", "CCCCCCCCCCx", "DDDDDDDDDDDDe", "DDDDDDDDDDDDe", 
    "AAAAAAAAAAAAAn", "AAAAAAAAAAAAAn", "CCCCCCCCCCx", "CCCCCCCCCCx", 
    "CCCCCCCCCCx", "DDDDDDDDDDDDe", "DDDDDDDDDDDDe", "DDDDDDDDDDDDe", 
    "DDDDDDDDDDDDe", "DDDDDDDDDDDDe", "DDDDDDDDDDDDe", "DDDDDDDDDDDDe", 
    "CCCCCCCCCCx", "DDDDDDDDDDDDe", "AAAAAAAAAAAAAn", "AAAAAAAAAAAAAn", 
    "CCCCCCCCCCx", "AAAAAAAAAAAAAn", "CCCCCCCCCCx", "DDDDDDDDDDDDe", 
    "CCCCCCCCCCx", "DDDDDDDDDDDDe", "CCCCCCCCCCx", "DDDDDDDDDDDDe", 
    "CCCCCCCCCCx", "LLLLLLLLLLLLLn", "LLLLLLLLLLLLLn", "LLLLLLLLLLLLLn", 
    "CCCCCCCCCCx", "LLLLLLLLLLLLLn", "AAAAAAAAAAAAAn", "AAAAAAAAAAAAAn", 
    "AAAAAAAAAAAAAn", "LLLLLLLLLLLLLn", "LLLLLLLLLLLLLn", "AAAAAAAAAAAAAn", 
    "AAAAAAAAAAAAAn", "CCCCCCCCCCx", "AAAAAAAAAAAAAn", "AAAAAAAAAAAAAn", 
    "AAAAAAAAAAAAAn", "CCCCCCCCCCx", "AAAAAAAAAAAAAn", "AAAAAAAAAAAAAn", 
    "AAAAAAAAAAAAAn", "CCCCCCCCCCx", "AAAAAAAAAAAAAn", "LLLLLLLLLLLLLn", 
    "LLLLLLLLLLLLLn", "AAAAAAAAAAAAAn", "AAAAAAAAAAAAAn", "LLLLLLLLLLLLLn", 
    "AAAAAAAAAAAAAn", "CCCCCCCCCCx", "CCCCCCCCCCx", "CCCCCCCCCCx", 
    "AAAAAAAAAAAAAn", "AAAAAAAAAAAAAn", "AAAAAAAAAAAAAn", "CCCCCCCCCCx", 
    "AAAAAAAAAAAAAn", "AAAAAAAAAAAAAn", "AAAAAAAAAAAAAn", "AAAAAAAAAAAAAn", 
    "CCCCCCCCCCx", "CCCCCCCCCCx", "LLLLLLLLLLLLLn", "AAAAAAAAAAAAAn", 
    "CCCCCCCCCCx", "AAAAAAAAAAAAAn", "AAAAAAAAAAAAAn", "AAAAAAAAAAAAAn", 
    "AAAAAAAAAAAAAn", "AAAAAAAAAAAAAn", "AAAAAAAAAAAAAn", "AAAAAAAAAAAAAn", 
    "AAAAAAAAAAAAAn", "LLLLLLLLLLLLLn", "LLLLLLLLLLLLLo", "LLLLLLLLLLLLLo", 
    "LLLLLLLLLLLLLn", "LLLLLLLLLLLLLn", "LLLLLLLLLLLLLo", "NNNNNNNNNNNr", 
    "NNNNNNNNNNNr", "LLLLLLLLLLLLLn", "LLLLLLLLLLLLLn", "NNNNNNNNNNNr", 
    "NNNNNNNNNNNr", "NNNNNNNNNNNr", "NNNNNNNNNNNr", "NNNNNNNNNNNr", 
    "LLLLLLLLLLLLLo", "LLLLLLLLLLLLLo", "NNNNNNNNNNNr", "LLLLLLLLLLLLLo", 
    "NNNNNNNNNNNr", "NNNNNNNNNNNr", "NNNNNNNNNNNr", "NNNNNNNNNNNr", 
    "NNNNNNNNNNNr", "LLLLLLLLLLLLLn", "LLLLLLLLLLLLLn", "NNNNNNNNNNNr", 
    "LLLLLLLLLLLLLo", "LLLLLLLLLLLLLo", "LLLLLLLLLLLLLo", "LLLLLLLLLLLLLn", 
    "LLLLLLLLLLLLLo", "NNNNNNNNNNNr", "NNNNNNNNNNNr", "LLLLLLLLLLLLLn", 
    "LLLLLLLLLLLLLn", "NNNNNNNNNNNr", "LLLLLLLLLLLLLn", "NNNNNNNNNNNr", 
    "NNNNNNNNNNNr", "LLLLLLLLLLLLLo", "LLLLLLLLLLLLLo", "CCCCCCCCCCx", 
    "LLLLLLLLLLLLLo", "DDDDDDDDDDDDe", "CCCCCCCCCCx", "LLLLLLLLLLLLLo", 
    "LLLLLLLLLLLLLo", "LLLLLLLLLLLLLo", "DDDDDDDDDDDDe", "DDDDDDDDDDDDe", 
    "DDDDDDDDDDDDe", "CCCCCCCCCCx", "DDDDDDDDDDDDe", "CCCCCCCCCCx", 
    "CCCCCCCCCCx", "CCCCCCCCCCx", "CCCCCCCCCCx", "DDDDDDDDDDDDe", 
    "CCCCCCCCCCx", "CCCCCCCCCCx", "DDDDDDDDDDDDe", "DDDDDDDDDDDDe", 
    "DDDDDDDDDDDDe", "DDDDDDDDDDDDe", "LLLLLLLLLLLLLo", "DDDDDDDDDDDDe", 
    "DDDDDDDDDDDDe", "CCCCCCCCCCx", "CCCCCCCCCCx", "AAAAAAAAAAo", 
    "AAAAAAAAAAo", "AAAAAAAAAAo", "AAAAAAAAAAo", "AAAAAAAAAAo", 
    "AAAAAAAAAAo", "CCCCCCCCCCx", "CCCCCCCCCCCCCCx", "AAAAAAAAAAo", 
    "AAAAAAAAAAo", "AAAAAAAAAAo", "AAAAAAAAAAo", "AAAAAAAAAAo", 
    "AAAAAAAAAAo", "CCCCCCCCCCCCCCx", "AAAAAAAAAAo", "CCCCCCCCCCCCCCx", 
    "SSSSSSSSSSd", "SSSSSSSSSSd", "GGGGGGGGGGGGGi", "SSSSSSSSSSd", 
    "SSSSSSSSSSd", "AAAAAAAAAAo", "SSSSSSSSSSd", "SSSSSSSSSSd", 
    "AAAAAAAAAAo", "SSSSSSSSSSd", "AAAAAAAAAAo", "SSSSSSSSSSd", 
    "SSSSSSSSSSd", "SSSSSSSSSSd", "AAAAAAAAAAo", "SSSSSSSSSSd", 
    "GGGGGGGGGGGGGi", "GGGGGGGGGGGGGi", "GGGGGGGGGGGGGi", "GGGGGGGGGGGGGi", 
    "GGGGGGGGGGGGGi", "GGGGGGGGGGGGGi", "SSSSSSSSSSd", "LLLLLLLLLLLLLLLLLLLl", 
    "LLLLLLLLLLLLLLLLLLLl", "LLLLLLLLLLLLLLLLLLLl", "LLLLLLLLLLLLLLLLLLLl", 
    "LLLLLLLLLLLLLLLLLLLl", "LLLLLLLLLLLLLLLLLLLl", "LLLLLLLLLLLLLLLLLLLl", 
    "LLLLLLLLLLLLLLLLLLLl", "LLLLLLLLLLLLLLLLLLLl", "LLLLLLLLLLLLLLLLLLLl", 
    "LLLLLLLLLLLLLLLLLLLl", "LLLLLLLLLLLLLLLLLLLl", "LLLLLLLLLLLLLLLLLLLl", 
    "LLLLLLLLLLLLLLLLLLLl", "LLLLLLLLLLLLLLLLLLLl", "LLLLLLLLLLLLLLLLLLLl", 
    "LLLLLLLLLLLLLLLLLLLl", "LLLLLLLLLLLLLLLLLLLl", "LLLLLLLLLLLLLLLLLLLl", 
    "JJJJJJJJJJJJy", "JJJJJJJJJJJJy", "JJJJJJJJJJJJy", "JJJJJJJJJJJJJJJJJJd", 
    "JJJJJJJJJJJJJJJJJJd", "JJJJJJJJJJJJJJJJJJd", "JJJJJJJJJJJJy", 
    "JJJJJJJJJJJJJJJJJJd", "JJJJJJJJJJJJy", "JJJJJJJJJJJJy", 
    "LLLLLLLLLLn", "CCCCCCCCCCCCd", "CCCCCCCCCCCCd", "CCCCCCCCCCCCd", 
    "CCCCCCCCCCCCd", "CCCCCCCCCCCCd", "OOOOOOOOOOOOm", "OOOOOOOOOOOOm", 
    "LLLLLLLLLLn", "CCCCCCCCCCCCd", "OOOOOOOOOOOOm", "CCCCCCCCCCCCd", 
    "CCCCCCCCCCCCd", "LLLLLLLLLLn", "CCCCCCCCCCCCd", "CCCCCCCCCCCCd", 
    "CCCCCCCCCCCCd", "LLLLLLLLLLn", "LLLLLLLLLLn", "LLLLLLLLLLn", 
    "OOOOOOOOOOOOm", "CCCCCCCCCCCCd", "LLLLLLLLLLn", "CCCCCCCCCCCCd", 
    "CCCCCCCCCCCCd", "OOOOOOOOOOOOm", "CCCCCCCCCCCCd", "CCCCCCCCCCCCd", 
    "CCCCCCCCCCCCd", "CCCCCCCCCCCCd", "CCCCCCCCCCCCd", "CCCCCCCCCCCCd", 
    "CCCCCCCCCCCCd", "CCCCCCCCCCCCd", "LLLLLLLLLLn", "LLLLLLLLLLn", 
    "LLLLLLLLLLn", "LLLLLLLLLLn", "OOOOOOOOOOOOm", "LLLLLLLLLLLLLLLLLLLl", 
    "LLLLLLLLLLLLLLLLLLLl", "LLLLLLLLLLLLLLLLLLLl", "LLLLLLLLLLLLLLLLLLLl", 
    "LLLLLLLLLLLLLLLLLLLl", "LLLLLLLLLLLLLLLLLLLl", "LLLLLLLLLLLLLLLLLLLl", 
    "LLLLLLLLLLLLLLLLLLLl", "LLLLLLLLLLLLLLLLLLLl", "LLLLLLLLLLLLLLLLLLLl", 
    "LLLLLLLLLLLLLLLLLLLl", "AAAAAAAAAAo")), row.names = c(NA, 
-332L), class = c("tbl_df", "tbl", "data.frame"))

Solution

  • You can easily do this by fitting your categorical outcome as an actual 0/1 coded dummy effect. This is what happens anyway inside any fitting routine, but it's the subsequent predict methods that won't know what to do with where we want to go:

    ## This is what the design matrix looks like inside glmer()
    unique(model.matrix(~N_G_altnt_Q_YN, data=df))
    #>  (Intercept) N_G_altnt_Q_YN1
    #>          1               0
    #>          1               1
    
    ## Manually code our effect to be 0/1 (numeric)
    df$X <- as.integer(df$N_G_altnt_Q_YN == 1)
    
    ## Fit this numeric effect
    m_1 <- glmer(Preselected_0 ~ X + (X | File / Person_anon),
                 family = "binomial", data = df)
    

    I won't show it here but this changes nothing in your model's fixed or random estimates, it simply removed the factor type from the predictor. If you had more than two levels in this factor you'd have to create more dummies, but the same principle holds (and again, this is what model.matrix will do inside any model anyway).

    The big advantage is that we can now predict other values than 0/1 -- even outside these bounds if you were so inclined, although clearly that would be meaningless.

    ## Helper function to back-transform log odds
    expit <- function(x) 1/(1+exp(-x))
    
    ## Desired prediction range
    x <- seq(0, 1, length.out = 2E2)
    
    pred <- predict(m_1, data.frame(X = x), re.form = ~0, se.fit = TRUE) |>
       do.call(cbind, args = _) |>
       cbind(x) |>
       as.data.frame() |>
       dplyr::mutate(est = expit(fit),
                     ## Calculate Wald 95% confidence bounds
                     lower = expit(fit - se.fit*qnorm(.975)),
                     upper = expit(fit + se.fit*qnorm(.975)))
    

    We've done a few things in that last call: asked for fixed-effect predicted means and standard errors across the prediction range, and calculated a Wald-type 95% confidence interval using those. Finally, everything was back-transformed from the log odds scale to the response (probability) scale. You need to do that step last because you cannot calculate this confidence interval in the response scale directly.

    All that's left now is to produce a plot. I'll stick to base routines instead of e.g. ggplot2:

    plot(c(0,1), c(0,1), type="n", xlab="", ylab="", xaxt="none")
    axis(1, labels=c("no", "yes"), at=0:1)
    polygon(c(x, rev(x)), c(pred$upper, rev(pred$lower)), col="grey90", lty=0)
    lines(pred$x, pred$est, lwd=3)
    

    prediction plot

    A few closing notes: