Reputation: 549
I am using the plot_model function from the library sjPlot for diagnostic plots of a linear regression. If you have a univariate regression, it outputs 3 plots, if you have a multivariate regression then there are 4 plots. The plots update dynamically with checkboxGroupInput but I get 'Error: subscript out of bounds' where the 4th plot should be when I only have 1 input checked. I want the spot for the 4th plot to just return blank if there is only 1 input checked.
I include a sample of 150 rows generated with dput: [redacted]
library(sjPlot)
library(tidyverse)
regression_data <- read_csv("df.csv")
server <- function(input, output) {
regFormula <- reactive({
as.formula(paste("perc_suspensions", " ~ ", paste(input$iv1, collapse = "+")))
}) #reactive for linear regression
# then, put that formula into lm() for a linear regression
model <- reactive({
lm(regFormula(), regression.data)
})
# Diagnostic plots
output$plot_a<-renderPlot({
plot_model(model(), type = "diag")[[1]]
})
output$plot_b<-renderPlot({
plot_model(model(), type = "diag")[[2]]
})
output$plot_c<-renderPlot({
plot_model(model(), type = "diag")[[3]]
})
output$plot_d <- renderPlot({
plot_model(model(), type = "diag")[[4]]
})
# These were my futile attempts which did not work
# output$plot_d<- renderPlot({
# if(ncol(model()$model>2)){
# plot_model(model(), type = "diag")[[4]]} else{renderPlot({""})}
# })
# output$plot_d <- renderPlot({""}) #this does work in the application and outputs nothing so I tried to nest this in my other attempts but alas
# output$plot_d <- reactive({
# if(ncol(model()$model>2)){
# renderPlot({
# plot_model(model(), type = "diag")[[4]]
# })
# } else{
# renderPlot({""})
# }
# })
} #server render
ui <- shinyUI(fluidPage(
tabPanel(
"",
headerPanel("Header Panel PlaceHolder"),
sidebarLayout(
position = "right",
sidebarPanel(
h2("Build your model"),
br(),
checkboxGroupInput(
"iv1",
label = "Select any of the independent variables below to calculate your model. You can change your selection at any time.",
c("Average % of student attendance"="Attendance",
"Average number of new students per year"="New_student",
"Average number of students who withdraw from the school per year"="Withdrawals",
"% of student body that is African American" = "African_American",
"% of student body that is White" = "White",
"% of student body that is Asian" = "Asian",
"% of student body that is Latino" = "Latino",
"% of student body that is another race" = "Other",
"% of student body that is Pacific Islander" = "Pacific_Islander",
"Percentage of student body that is from a low income family" = "Low_income_family",
"Zip code" = "SCHOOL_ZIP",
"Type of school" = "SCHOOL_LEVEL_NAME",
"Drug infractions per 100 students" = "Drugs",
"Morals infractions per 100 students" = "Morals",
"Assaults per 100 students" = "Assaults",
"Weapons infractions per 100 students" = "Weapons",
"Thefts per 100 students" = "Thefts",
"Average percentage of teacher attendance" = "Teacher_attendance",
"Percentage of student body receiving special education" = "Special_education",
"Percentage of student body receiving gifted education" = "Gifted_education",
"Percentage of student body receiving ESL services" = "English_second_language",
"Average teacher salary" = "Average_salary"), # c
selected = c("Average_salary","Teacher_attendance")
#Note Average Salary is selected when the app starts
) # checkboxGroupInput
), #sidebarpanel
mainPanel(br(),
fluidRow(
plotOutput("plot_a"),
plotOutput("plot_b"),
plotOutput("plot_c"),
plotOutput("plot_d")
) #fluidrow for plot
)# mainPanel
) #sidebarlayout
) # tab panel
) # fluidpage
) #shinyUI
Upvotes: 0
Views: 300
Reputation: 84529
You are running plot_model(model(), type = "diag")
multiple times in your app. Put this list of plots in a reactive conductor instead:
Plots <- reactive({
plot_model(model(), type = "diag")
})
In this way you run this command only one time. Then:
output$plot_a<-renderPlot({
Plots()[[1]]
})
output$plot_b<-renderPlot({
Plots()[[2]]
})
output$plot_c<-renderPlot({
Plots()[[3]]
})
output$plot_d <- renderPlot({
req(length(Plots()) == 4)
Plots()[[4]]
})
Upvotes: 0
Reputation: 1234
If you just want to suppress the error message, adding try()
around plot_model()
will do what you want:
output$plot_a<-renderPlot({
try(plot_model(model(), type = "diag")[[1]])
})
output$plot_b<-renderPlot({
try(plot_model(model(), type = "diag")[[2]])
})
output$plot_c<-renderPlot({
try(plot_model(model(), type = "diag")[[3]])
})
output$plot_d <- renderPlot({
try(plot_model(model(), type = "diag")[[4]])
})
Upvotes: 1