简体   繁体   中英

I have fitted a GLM and failing to plot the model using ggplot

I have made a GLM and am trying to plot the model using ggplot using the following code. I think i need to add the type argument so that my model doesn't just produce a horizontal flat line. However i am struggling to fit it using the type argument as i run into this error message;

 Error in model.frame.default(Terms, newdata, na.action = na.action, xlev = 
 object$xlevels) : 
 object is not a matrix 

Here is my dataset and code used to get this if anyone knows the fix for this

my data (first 10 rows);

 aids
   cases quarter  date
 1      2       1 83.00
 2      6       2 83.25
 3     10       3 83.50
 4      8       4 83.75
 5     12       1 84.00
 6      9       2 84.25
 7     28       3 84.50
 8     28       4 84.75
 9     36       1 85.00
 10    32       2 85.25

my code used to create the model and plot

 model3 = glm(cases ~ date,
          data = aids,
          family = poisson(link='log'))


 #plotting the model (“link”, “response”, “terms”)
 plot_predictions <- function(model, type = 'response') {

   #make predictions
    preds <- predict(model, df)

   #plot
   df %>% 
    ggplot(aes(date, cases)) +
    geom_point() +
    geom_line(aes(date, preds), col = 'red') +
    ggtitle("Model 2 - Poisson GLM predicting cases") +
    theme(plot.title = element_text(hjust = 0.5, size = 12, face = 'bold'))
 }

 plot_predictions(model3, aids) 

dput output

dput(head(aids, 10))
structure(list(cases = c(2, 6, 10, 8, 12, 9, 28, 28, 36, 32), 
quarter = structure(c(1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 
2L), .Label = c("1", "2", "3", "4"), class = "factor"), date = 
c(83, 
83.25, 83.5, 83.75, 84, 84.25, 84.5, 84.75, 85, 85.25)), 
row.names = c(NA, 
10L), class = "data.frame")

You are reinventing the wheel a bit here. This can be done automatically in ggplot using geom_smooth

ggplot(aids, aes(date, cases)) +
    geom_point() +
    geom_smooth(col = 'red', se= FALSE, method = glm,
                method.args = list(family = poisson(link = 'log'))) +
    ggtitle("Model 2 - Poisson GLM predicting cases") +
    theme(plot.title = element_text(hjust = 0.5, size = 12, face = 'bold'))

在此处输入图像描述

You can even get the standard error to show by omitting se = FALSE :

ggplot(aids, aes(date, cases)) +
    geom_segment(aes(xend = date, yend = 0), color = "deepskyblue4") +
    geom_point(size = 3) +
    geom_smooth(col = 'red3', fill = "red3", method = glm, alpha = 0.1,
                method.args = list(family = poisson(link = 'log'))) +
    ggtitle("Model 2 - Poisson GLM predicting cases") +
    theme_minimal(base_size = 16) +
    theme(plot.title = element_text(hjust = 0.5, face = 'bold'))

在此处输入图像描述

Here's one that puts the predictions on the right scale:

library(tidyverse)
aids <- structure(list(cases = c(2, 6, 10, 8, 12, 9, 28, 28, 36, 32), 
               quarter = structure(c(1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 
                                     2L), .Label = c("1", "2", "3", "4"), class = "factor"), date = 
                 c(83, 
                   83.25, 83.5, 83.75, 84, 84.25, 84.5, 84.75, 85, 85.25)), 
          row.names = c(NA, 
                        10L), class = "data.frame")
model3 = glm(cases ~ date,
             data = aids,
             family = poisson(link='log'))


plot_predictions <- function(model, df, type = 'response') {
  require(tidyverse)
  #make predictions
  preds <- predict(model, df, type= type)
  
  #plot
  df %>% 
    ggplot(aes(date, cases)) +
    geom_point() +
    geom_line(aes(date, preds), col = 'red') +
    ggtitle("Model 2 - Poisson GLM predicting cases") +
    theme(plot.title = element_text(hjust = 0.5, size = 12, face = 'bold'))
}

plot_predictions(model3, aids)

Created on 2022-05-25 by the reprex package (v2.0.1)


Here's how you could do it with confidence intervals, though this will only work nicely in bivariate models. I've included an option using ggpredict() from the ggeffects package that will work in this and other circumstances. The trick here is that you've got to make the predictions on the link scale, make the confidence intervals from the standard errors of the predictions and then transform everything (fit, lower and upper bounds) through the inverse link.

library(tidyverse)
aids <- structure(list(cases = c(2, 6, 10, 8, 12, 9, 28, 28, 36, 32), 
                       quarter = structure(c(1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 
                                             2L), .Label = c("1", "2", "3", "4"), class = "factor"), date = 
                         c(83, 
                           83.25, 83.5, 83.75, 84, 84.25, 84.5, 84.75, 85, 85.25)), 
                  row.names = c(NA, 
                                10L), class = "data.frame")
model3 = glm(cases ~ date,
             data = aids,
             family = poisson(link='log'))


plot_predictions <- function(model, df, conf=.95, type = 'response') {
  require(tidyverse)
  #make predictions
  preds <- predict(model, df, type= "link", se.fit=TRUE)
  preds <- as.data.frame(preds[1:2])
  preds$x <- df$date
  preds <- preds %>% 
    mutate(lwr = fit - pnorm(1-(1-conf/2))*se.fit, 
           upr = fit + pnorm(1-(1-conf/2))*se.fit, 
           across(c(fit, lwr, upr), ~family(model)$linkinv(.x)))
  
  
  
  #plot
  ggplot(data=df, aes(date, cases)) +
    geom_ribbon(data=preds, aes(x=x, y=fit, ymin=lwr, ymax=upr), alpha=.25, fill="red", col="transparent") + 
    geom_line(data=preds, aes(x, fit), col = 'red') +
    geom_point() +
    ggtitle("Model 2 - Poisson GLM predicting cases") +
    theme(plot.title = element_text(hjust = 0.5, size = 12, face = 'bold'))
}

plot_predictions(model3, aids)

Here's the ggpredict() option:

library(ggeffects)
g <- ggpredict(model3, terms="date [all]")
plot(g, rawdata=TRUE)

Created on 2022-05-25 by the reprex package (v2.0.1)

You can also do this using broom::augment to add the predictions of your model to the data and plot that:

model3 %>%
    broom::augment() %>%
    ggplot(aes(date, cases)) +
    geom_point() +
    geom_line(aes(date, exp(.fitted)), col = 'red') +
    ggtitle("Model 2 - Poisson GLM predicting cases") +
    theme(plot.title = element_text(hjust = 0.5, size = 12, face = 'bold'))

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM