Search code examples
rshinyr-corrplot

Shiny : Automate a web app with fileInput() and selectizeInput()


I'm trying to automate a web app with fileInput() and selectizeInput() functions. Indeed, I would like to plot a correlogram according to the variable selected.

However, I get :

Error : supply both 'X'and 'Y' or a matrix-like 'X'

I think my problem comes from in this block of code :

data03 <- reactive({
file1 <- input$file
req(file1)
dataSet <- read_excel(file1$datapath)
col <- names(dataSet)
updateSelectizeInput(session = session, inputId = "corr02", choices = col)
})
observe({
varZ <- names(data03())
})
output$corrplot <- renderPlot({
 df <- data03()
 if(input$dataSubmit03){
   isolate({
       corr <- cor(x = df, method = "pearson", use  = "pairwise.complete.obs")
       corrplot(corr = corr, 
               type = "lower", 
               method = "circle", 
               tl.col = "black", 
               tl.srt = 45)
    })
   }
 })

This is the entire code that I used. Thanks for your help !

library(shiny)
library(xlsx)
library(corrplot)
library(readxl)

# File used for the example
data(iris)
write.xlsx(x = iris, file = "iris.xlsx")

ui <- fluidPage(
  navbarPage(
         tabPanel(title = "Presentation"),
         tabPanel(title = "Importing data",
                  sidebarLayout(
                    sidebarPanel(
                      fileInput(inputId = "file",
                                label = "Import a file",
                                accept = c(".xlsx", ".txt", ".csv")
                      )
                    ),
                    mainPanel(
                      width = 12,
                      verbatimTextOutput("table"))
                  )
         ),
         navbarMenu(title = "Descriptive analytics",
                    tabPanel(title = "Correlogram",
                             sidebarLayout(
                               sidebarPanel(
                                 selectizeInput(inputId = "corr02",
                                                label = "Select the variables:",
                                                choices = NULL,
                                                multiple = TRUE),
                                 br(),
                                 actionButton(inputId = "dataSubmit03", 
                                              label = "RUN")

                                 ),
                               mainPanel(
                                 plotOutput(outputId = "corrplot",
                                            height = "600px")
                               )
                               )
                               )
                    )
                    )
                    )

server <- function(input, output, session) {
df <- reactive({
inFile <- input$file
db <- read_excel(inFile$datapath)
db <- data.frame(db)
})
df1 <- reactive({
inFile <- input$file
db <- read_excel(inFile$datapath, na = "NA")
db <- data.frame(db)
})
data03 <- reactive({
file1 <- input$file
req(file1)
dataSet <- read_excel(file1$datapath)
col <- names(dataSet)
updateSelectizeInput(session = session, inputId = "corr02", choices = col)
})
observe({
varZ <- names(data03())
})
output$corrplot <- renderPlot({
 df <- data03()
 if(input$dataSubmit03){
   isolate({
       corr <- cor(x = df, method = "pearson", use  = "pairwise.complete.obs")
       corrplot(corr = corr, 
               type = "lower", 
               method = "circle", 
               tl.col = "black", 
               tl.srt = 45)
    })
   }
 })
}

shinyApp(ui = ui, server = server)

EXPECTATION

enter image description here

REALITY

enter image description here


Solution

  • This should work with your ui() unchanged. Summary of what I changed:

    1. I prefer to have update() functions in their own observe() calls (not sure if this is the best way though)
    2. I also subset the column selection choices so that you can only select numeric columns.
    3. In the renderPlot() function, you never subset for the columns that you select. (that's the df <- df[,input$corr02])
    4. The way that I usually write these requires that if statement at the beginning (if (!is.null(input$corr02)), otherwise it will throw an error immediately, before you have a chance to select which columns.

    code:

    server <- function(input, output, session) {
    
      data03 <- reactive({ if (!is.null(input$file)) {
        file1 <- input$file
        req(file1)
        dataSet <- read_excel(file1$datapath)
        return(dataSet)
      }}) # reactive
    
      observe({ if (!is.null(data03())) {
        col_v <- names(data03())
        whichNum_v <- which(sapply(data03(), class) == "numeric")
        col_v <- col_v[whichNum_v]
        updateSelectizeInput(session = session, inputId = "corr02", choices = col_v)
      }}) # observe
    
      output$corrplot <- renderPlot({ 
    
        ## Only run if selection has been made
        if (!is.null(input$corr02)) {
    
          ## Subset columns
          df <- data03()
          df <- df[,input$corr02]
    
          ## Make plot on click
          if(input$dataSubmit03){
            isolate({
              corr <- cor(x = df, method = "pearson", use  = "pairwise.complete.obs")
              corrplot(corr = corr, 
                       type = "lower", 
                       method = "circle", 
                       tl.col = "black", 
                       tl.srt = 45)})
          } # fi
        } # fi
      }) # renderPlot
    } # server