AK47
AK47

Reputation: 1328

Change variable class from Shiny UI

My goal is to change variables data class of uploaded dataset. data class should be selected by the user in ui.

As uploaded datasets might be different, I use lapply to create selectInput for each column in the dataset. Piece of code below generates selectInputs for each column called variable_i, where i is a number of column.

lapply(seq(ncol( rawdata() )),function(i){

            selectInput(inputId = paste0("variable","_",i),label = colnames(rawdata())[i],
                        choices = c("factor", "numeric", "integer", "character"),
                        selected = class(rawdata()[,i])
            )
          })

Using this selectInput user can input data class. My question is, how to change class of variables using inputed info from input$variable_i as input names are dynamic and I can't simply call it.

Maybe is there any other approaches to change data class from UI?

Whole code I use below. If the problem will be solved, I'll share full working code.

library(summarytools)
library("shiny")
library("shinydashboard")
library("dplyr")
# Server ------------------------------------------------------------------

server <- function(input, output,session) {


#upload file from PC
rawdata <- reactive({

    inFile <- input$fileIn

    if (is.null(inFile))
        return(NULL)
        read.csv(inFile$datapath, sep=input$Separator)

  })




#Get data example
output$DataCheck <- renderTable({

                      head(rawdata())

                      })



#get data summary
output$summaryTable <- renderUI({

  out <- print(dfSummary( rawdata(),graph.magnif = 0.8), style = 'grid', omit.headings = TRUE, method = 'render',bootstrap.css = FALSE)
  out[[3]][[2]][[1]]
})



output$colname_in <- renderUI({

  selectInput(inputId = "colname",
              label = "Choose column",
              choices = c("",colnames(rawdata())),
              selected = "")

})



observeEvent(input$change_class, {

  v$data <- eval(parse(text = paste0('v$data %>% mutate(',
                                     input$colname,
                                     ' = as.',
                                     input$class,
                                     '(',
                                     input$colname,
                                     '))')
  )
  )

})


}
# UI ----------------------------------------------------------------------

ui <- bootstrapPage(

  dashboardPage(

    dashboardHeader(title = "AK47"
                    ), #dashboardHeader

 #Sidebar--------------------------------------------------------------------------

  dashboardSidebar(

      sidebarMenu(
                   id = "tabs",
                   menuItem("Step 1: Input Data", tabName = "Input", icon = icon("cog"))

                  ) #sidebarMenu

    ),#dashboardSidebar



 #Body-------------------------------------------------------------------------------------

 dashboardBody(

   tabItems(

     tabItem("Input",

           fluidRow(  
             box(width = 4,title = 'Upload your data file:',solidHeader = T,status = 'primary',


                 #Upload file from PC
                 fileInput('fileIn',label = 'Select the data'),

                 #choose separator
                 radioButtons("Separator","Choose separator:", inline = TRUE,
                              choices=c(Comma=",",
                                        Semicolon=";",
                                        Tab="\t"),  selected = ";")

             ) #box
           ), #fluidRiw


           fluidRow(  
             box(width = 12,title = 'Check the data for correct separator:',solidHeader = F ,status = 'primary',

                 tableOutput('DataCheck'),
                 tags$hr()

             ) #box
           ),  #fluidRow

           fluidRow(  
             box(width = 12,title = 'Change variable typesr:',solidHeader = F ,status = 'primary',

                 uiOutput("colname_in"),

                 selectInput(inputId = "class",
                             label = "Choose class",
                             choices = c("", "factor", "numeric", "integer", "character"),
                             selected = ""),

                 actionButton("change_class",
                              "Change class"),

                 uiOutput('summaryTable'),

                 tags$hr()

             ) #box
           )  #fluidRow


     ) #tabItem



   ) #tabItems


      )#dashboardBody  




  )#dashboardPage
)#bootstrapPage

shinyApp(ui, server)

Upvotes: 1

Views: 1138

Answers (1)

TimTeaFan
TimTeaFan

Reputation: 18561

Instead of generating one selectInput for each column, I would use two selectInputs, one for column name, one for class and an action button to change the class.

Here is my approach. It might not be perfect, but could be a start.

library("shiny")
library("dplyr")
library("ggplot2")


shinyApp(

    ui = fluidPage(

        # Layout with sidebar
        sidebarLayout(

            ## Sidebar -----
            sidebarPanel(

                # > some example input on sidebar -----

                uiOutput("colname_in"),
                selectInput(inputId = "class",
                            label = "Choose class",
                            choices = c("", "factor", "numeric", "integer", "character"),
                            selected = ""),
                actionButton("change_class",
                             "Change class")

            ), # closes Sidebar-Panel



            # Main-Panel ------
            mainPanel(


                             tableOutput("print")





            )  # closes mainPanel                      

        ) # closes sidebarLayout

    ), # closes fluidPage


    # Server ------
    server = function(input, output, session){

        v <- reactiveValues(data = iris)


        output$colname_in <- renderUI({

            selectInput(inputId = "colname",
                        label = "Choose column",
                        choices = c("",colnames(v$data)),
                        selected = "")

        })

        observeEvent(input$change_class, {

            v$data <- eval(parse(text = paste0('v$data %>% mutate(',
                                     input$colname,
                                     ' = as.',
                                     input$class,
                                     '(',
                                     input$colname,
                                     '))')
                               )
                 )

        })



        output$print <- renderTable({

            print(input$colname)
            print(input$class)
            print(input$change_class)

                v$data

        })

    } # Closes server
) # Closes ShinyApp

Update Below I integrated my approach into your code. It is important to read the csv into the reactiveValue v$data which works inside an observeEvent.

library("summarytools")
library("shiny")
library("shinydashboard")
library("dplyr")
# Server ------------------------------------------------------------------

server <- function(input, output,session) {


    #upload file from PC
    v = reactiveValues(path = NULL)


    observeEvent(input$fileIn, {
        req(input$fileIn)
        v$data <- read.csv(input$fileIn$datapath, sep = input$Separator)


    })




    #Get data example
    output$DataCheck <- renderTable({

        req(v$data)
        head(v$data)

    })



    #get data summary
    output$summaryTable <- renderUI({

        req(v$data)

        out <- print(dfSummary(v$data,graph.magnif = 0.8), style = 'grid', omit.headings = TRUE, method = 'render',bootstrap.css = FALSE)
        out[[3]][[2]][[1]]

    })



    output$colname_in <- renderUI({

        req(v$data)

        selectInput(inputId = "colname",
                    label = "Choose column",
                    choices = c("",colnames(v$data)),
                    selected = "")

    })



    observeEvent(input$change_class, {

        v$data <- eval(parse(text = paste0('v$data %>% mutate(',
                                           input$colname,
                                           ' = as.',
                                           input$class,
                                           '(',
                                           input$colname,
                                           '))')
        )
        )

    })


}
# UI ----------------------------------------------------------------------

ui <- bootstrapPage(

    dashboardPage(

        dashboardHeader(title = "AK47"
        ), #dashboardHeader

        #Sidebar--------------------------------------------------------------------------

        dashboardSidebar(

            sidebarMenu(
                id = "tabs",
                menuItem("Step 1: Input Data", tabName = "Input", icon = icon("cog"))

            ) #sidebarMenu

        ),#dashboardSidebar



        #Body-------------------------------------------------------------------------------------

        dashboardBody(

            tabItems(

                tabItem("Input",

                        fluidRow(  
                            box(width = 4,title = 'Upload your data file:',solidHeader = T,status = 'primary',


                                #Upload file from PC
                                fileInput('fileIn',label = 'Select the data'),

                                #choose separator
                                radioButtons("Separator","Choose separator:", inline = TRUE,
                                             choices=c(Comma=",",
                                                       Semicolon=";",
                                                       Tab="\t"),  selected = ";")

                            ) #box
                        ), #fluidRiw


                        fluidRow(  
                            box(width = 12,title = 'Check the data for correct separator:',solidHeader = F ,status = 'primary',

                                tableOutput('DataCheck'),
                                tags$hr()

                            ) #box
                        ),  #fluidRow

                        fluidRow(  
                            box(width = 12,title = 'Change variable typesr:',solidHeader = F ,status = 'primary',

                                uiOutput("colname_in"),

                                selectInput(inputId = "class",
                                            label = "Choose class",
                                            choices = c("", "factor", "numeric", "integer", "character"),
                                            selected = ""),

                                actionButton("change_class",
                                             "Change class"),

                                uiOutput('summaryTable'),

                                tags$hr()

                            ) #box
                        )  #fluidRow


                ) #tabItem



            ) #tabItems


        )#dashboardBody  




    )#dashboardPage
)#bootstrapPage

shinyApp(ui, server)

Upvotes: 2

Related Questions