Search code examples
rshinyshiny-reactivity

How to develop a new reactive data frame which takes columns from another reactive data frame and change data types to factor or numeric?


I use fileInput() to transfer the data inside a reactive data frame named theData(). I need to change some of the columns to factors by as.factor() function. I know I cannot modify a reactive data frame. So I define new reactive data frame which gets enteries from a checkboxGroupInput().

I already asked a similar question about changing to factors for static data but since in this case the data in imported by fileInput I thought it is appropriate to ask it.

This is the code

####################################################
# ui.r
####################################################

library(shiny)
library(shinydashboard)
library(shinyjs)
library(dplyr)
#library(caret)

input_csv_file <- fileInput(inputId = "csv_file",label = "",multiple = F)

input_xcat <- checkboxGroupInput(inputId = "xcat", label = "select categorical x",choices = "")


# inputs ###############################



input_csv_file <- fileInput(inputId = "csv_file",label = "",multiple = F)



#Header####
dashHeader <- dashboardHeader(title = "salam")
dashSidebar <- dashboardSidebar(sidebarMenu(
  menuItem(tabName = "tab_1", text = "page 1"),
  menuItem(tabName = "tab_2", text = "page 2")
))
dashBody <- dashboardBody(
  tabItems(
    tabItem(tabName = "tab_1", 
            # csv_file ####################################################################################
            fluidRow(
              box(width = 4, height = 200, 
                  input_csv_file
              ),
              box(width = 6, height = 150,
                  verbatimTextOutput("csv_file_res")
              )
            ),
            # #############################################################################
            fluidRow(
              box(width = 4, height = 200,
                verbatimTextOutput("str_res")
              ),
              box(width = 4, height = 200,
                input_xcat
              )
            )
            
    ),
    tabItem(tabName = "tab_2")
  )
)




dashboardPage(
  header = dashHeader,
  sidebar = dashSidebar,
  body = dashBody,
  title = "salam",
  skin = "red"
)


##############################################################
# server
##############################################################



library(shiny)
library(dplyr)

server <- function(input, output, session){
  
  # file uploud ###################################

  theData <- reactive({
    if(is.null(input$csv_file)){
      return(NULL)
    }
    read.csv(input$csv_file$datapath, header = T)
  })
  
  
  
  output$csv_file_res <- renderPrint({
    head(theData() )
  })
  
  # var selection #####################################
  
  observe({
    updateCheckboxGroupInput(session = session, inputId = "xcat", label = "select categorical x", choices = names( theData() ), selected = names(theData())[2] )
  })
    
  
  
  
  # str #####################################
  
  xcat_sel <- reactive({
                        {if(is.null(input$csv_file)){
                          return(NULL)
                        }
                          input$xcat
                        }
                      })
  
  theData_2 <- reactive({if(is.null(input$csv_file)){
                          return(NULL)
                        }
                        mutate(theData(), xcat_sel() = as.factor(xcat_sel())) 
                        })
  
  output$str_res <- renderPrint( str(theData_2() )  )
  
  # end ###############################  
}





Solution

  • Here's a possible solution using across with mutate.

      theData_2 <- reactive({
        mutate(theData(), across(all_of(input$xcat), as.factor))
      })
    

    Full code:

    I made some minor edits like adding req function in some places.

    ####################################################
    # ui.r
    ####################################################
    
    library(shiny)
    library(shinydashboard)
    library(shinyjs)
    library(dplyr)
    # library(caret)
    
    input_csv_file <- fileInput(inputId = "csv_file", label = "", multiple = F)
    input_xcat <- checkboxGroupInput(inputId = "xcat", label = "select categorical x", choices = NULL)
    input_csv_file <- fileInput(inputId = "csv_file", label = "", multiple = F)
    
    
    # Header####
    dashHeader <- dashboardHeader(title = "salam")
    dashSidebar <- dashboardSidebar(sidebarMenu(
      menuItem(tabName = "tab_1", text = "page 1"),
      menuItem(tabName = "tab_2", text = "page 2")
    ))
    dashBody <- dashboardBody(
      tabItems(
        tabItem(
          tabName = "tab_1",
          # csv_file ####################################################################################
          fluidRow(
            box(
              width = 4, height = 200,
              input_csv_file
            ),
            box(
              width = 6, height = 150,
              verbatimTextOutput("csv_file_res")
            )
          ),
          # #############################################################################
          fluidRow(
            box(
              width = 4, height = 200,
              verbatimTextOutput("str_res")
            ),
            box(
              width = 4, height = 200,
              input_xcat
            )
          )
        ),
        tabItem(tabName = "tab_2")
      )
    )
    
    ui <- dashboardPage(
      header = dashHeader,
      sidebar = dashSidebar,
      body = dashBody,
      title = "salam",
      skin = "red"
    )
    
    server <- function(input, output, session) {
      theData <- reactive({
        req(input$csv_file)
        read.csv(input$csv_file$datapath, header = T)
      })
      output$csv_file_res <- renderPrint({
        head(theData())
      })
      observe({
        updateCheckboxGroupInput(session = session,
                                 inputId = "xcat",
                                 label = "select categorical x",
                                 choices = names(theData()),
                                 selected = names(theData())[2])
      })
      theData_2 <- reactive({
        mutate(theData(), across(all_of(input$xcat), as.factor))
      })
      output$str_res <- renderPrint({
        #str functin is also an option
        glimpse(theData_2())
        })
    }
    
    shinyApp(ui, server)
    

    enter image description here