Home > Back-end >  Convert the class of selected columns of dynamic dataframe to numeric in a shiny app
Convert the class of selected columns of dynamic dataframe to numeric in a shiny app

Time:01-27

I have the shiny app below in which Im displaying all the column names of the initial dataframe as well as their class() in a table.

What I want to do is select a a column and after pressing the actionButton() to convert it to numeric. In this case lets choose case_id.

The new dataset is initial2 but it has to be available for use even if we convert one of its variables to numeric or not. How can I do this?

Also the Class in the table with the classes for case_id should be converted from character to numeric after pressing the actionButton()

The dataframe may be diffrent every time.

## app.R ##
library(shiny)
library(shinydashboard)
library(DT)
library(tibble)
library(tidyverse) # for the tibble
initial<-structure(list(case_id = c("3397364", "3397364"), action = c("3397364-RAAMELK", 
                                                                      "3397364-RAAMELK"), resource = c("RAAMELK", "RAAMELK"), lifecycle = c(1, 
                                                                                                                                            1), registration_type = structure(1:2, .Label = c("start", "complete"
                                                                                                                                            ), class = "factor"), timestamp = structure(c(1667523600, 1667531220
                                                                                                                                            ), tzone = "UTC", class = c("POSIXct", "POSIXt")), activity = c("RAAMELK", 
                                                                                                                                                                                                            "RAAMELK"), activity_description = c("Forbrukt r<e5>melk", "Forbrukt r<e5>melk"
                                                                                                                                                                                                            ), ...9 = c(NA, NA), product = c("K101152", "K101152"), product_type_text = c("200100 - Milk", 
                                                                                                                                                                                                                                                                                          "200100 - Milk"), qty = c(NA, 31), in_out = c("in", "out"), qty_scrap = c(NA_real_, 
                                                                                                                                                                                                                                                                                                                                                                    NA_real_), `FP ordre` = c(NA_character_, NA_character_), Artikkeltype = c("SF", 
                                                                                                                                                                                                                                                                                                                                                                                                                                              "SF"), .order = 1:2), row.names = c(NA, -2L), class = c("eventlog", 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      "log", "tbl_df", "tbl", "data.frame"), case_id = "case_id", activity_id = "activity", activity_instance_id = "action", lifecycle_id = "registration_type", resource_id = "resource", timestamp = "timestamp")
shinyApp(
  ui = dashboardPage(
    dashboardHeader(),
    dashboardSidebar(),
    dashboardBody(
      dataTableOutput("dt0"),
      dataTableOutput("dt"),
      selectInput("cols","Select column to convert",choices = colnames(initial),multiple = F,selected =colnames(initial)[1] ),
      actionButton("conv","Convert to numeric")
    )
  ),
  server = function(input, output, session) { # add session so we can update

initial<-reactive({
validate(
  need(!is.null(input$file1), 'No data exists, please upload a csv')
)
# p<-read.csv(inFile$datapath, header = T,sep = 
#input$separator,na.strings=c("",".","NA"))
   })   

     output$dt0<-renderDataTable({
      
      datatable(initial)
    }) 
    output$dt<-renderDataTable({
      
      dat<-data.frame(tibble(Name = colnames(initial), Class = sapply(initial, function(x) 
        paste(class(x), collapse=", "))))
      
      datatable(dat)
    }) 
    initial2<-reactive({input$conv
      initial #after processing or not
    })
  }
)

CodePudding user response:

One option would be to use a reactiveVal which you could init with your initial dataset. The reactiveVal could then be in your renderDataTable and be updated via an observeEvent triggered by the actionButton. For the conversion I use lapply which allows to convert multiple cols at once if desired.

library(shiny)
library(shinydashboard)
library(DT)
library(tibble)
library(tidyverse)

shinyApp(
  ui = dashboardPage(
    dashboardHeader(),
    dashboardSidebar(),
    dashboardBody(
      dataTableOutput("dt0"),
      dataTableOutput("dt"),
      selectInput("cols", "Select column to convert", choices = colnames(initial), multiple = F, selected = colnames(initial)[1]),
      actionButton("conv", "Convert to numeric")
    )
  ),
  server = function(input, output, session) { # add session so we can update
    dat <- reactiveVal(initial)
    
    output$dt0 <- renderDataTable({
      datatable(dat())
    })
    
    output$dt <- renderDataTable({
      dat <- data.frame(tibble(Name = colnames(dat()), Class = sapply(dat(), function(x) {
        paste(class(x), collapse = ", ")
      })))

      datatable(dat)
    })
    
    observeEvent(input$conv, {
      x <- dat()
      x[input$cols] <- lapply(x[input$cols], as.numeric)
      dat(x)
    })
  }
)

EDIT One option would be to init the reactiveVal as an empty data frame. Then use e.g. an observeEvent to uplaod your data and to init the reactiveVal with the uploaded data. As an example I added a fileInput to your app:

shinyApp(
  ui = dashboardPage(
    dashboardHeader(),
    dashboardSidebar(),
    dashboardBody(
      fileInput("upload", "Upload a file"),
      dataTableOutput("dt0"),
      dataTableOutput("dt"),
      selectInput("cols", "Select column to convert", choices = NULL, multiple = F),
      actionButton("conv", "Convert to numeric")
    )
  ),
  server = function(input, output, session) { # add session so we can update
    dat <- reactiveVal(data.frame())
    
    observeEvent(input$upload, {
      dat(read.csv(input$upload$datapath))
      
      updateSelectInput(inputId = "cols", choices = colnames(dat()), selected = colnames(dat())[[1]])
    })
    
    output$dt0 <- renderDataTable({
      datatable(dat())
    })
    
    output$dt <- renderDataTable({
      dat <- data.frame(tibble(Name = colnames(dat()), Class = sapply(dat(), function(x) {
        paste(class(x), collapse = ", ")
      })))

      datatable(dat)
    })
    
    observeEvent(input$conv, {
      x <- dat()
      x[input$cols] <- lapply(x[input$cols], as.numeric)
      dat(x)
    })
  }
)
  • Related