Home > OS >  Adjust features with selectInput in shiny app
Adjust features with selectInput in shiny app

Time:03-14

The code below generates an output table according to the weights selected by numericInput. This is working fine. The method involved for calculation is the WSM (weighted sum model). For this method it is necessary to choose the weights, which is already being done correctly in the app below, and also if a certain criterion is to maximize or minimize. However, that last question is not being done automatically in code. Notice that it is like this:

scaled <- df1 |>
      mutate(Coverage = min(Coverage) / Coverage, #minimize
             
             Production = Production / max(Production)) #maximize

That is, I manually selected that Coverage is minimize and Production is maximize, but for example it could be the other way around. That's why I created two selectInputs, where the person chooses whether he wants to maximize or minimize a certain criterion. Now how can tweak this in the shiny code so that it stays automatically?

library(shiny)
library(DT)
library(dplyr)
library(shinyjs)
library(MCDM)

df1 <- structure(list(n = c(2, 3, 4, 5, 6, 7, 8, 9, 10, 11), 
                      Coverage = c(0.0363201192049018, 0.0315198954715543,
                                   0.112661460735583, 0.112661460735583, 0.112661460735583, 0.0813721071219816,
                                   0.0862146652218061, 0.0697995564757394, 0.0599194966471805,
                                   0.0507632014547115), 
                      Production =
                        c(1635156.04305, 474707.64025, 170773.40775, 64708.312, 64708.312, 64708.312,
                          949.72635, 949.72635, 949.72635, 949.72635)),
                 class = "data.frame", row.names = c(NA,-10L))

ui <- fluidPage(
  useShinyjs(),
  
  column(4,
         wellPanel(
           numericInput("weight1",label = h4("Weight 1"), min = 0, max = 1, value = NA, step = 0.1),
           selectInput("maxmin1", label = h5("Maximize or Minimize?"),choices = list("Maximize " = 1, "Minimize" = 2), selected = ""),
         
           disabled(numericInput("weight2",label = h4("Weight 2"), min = 0,max = 1,value = NA,step = 0.1)),
           selectInput("maxmin2", label = h5("Maximize or Minimize?"),choices = list("Maximize " = 1, "Minimize" = 2), selected = ""),
           
           helpText("The sum of weights should be equal to 1")
         )),
  hr(),
  column(8,
         tabsetPanel(tabPanel("Method1", DTOutput('table1'))),
         tabsetPanel(tabPanel("Method2", DTOutput('table2')))))

server <- function(input, output, session) {
  
  scaled <- reactive({
    
    weights <- c(req(input$weight1), req(input$weight2))
    
    scaled <- df1 |>
      mutate(Coverage = min(Coverage) / Coverage, #minimize
             
             Production = Production / max(Production)) #maximize
    
    scaled <- scaled |>
      rowwise() |>
      mutate(`Performance Score` = weighted.mean(c(Coverage, Production), w = weights))
    
    scaled$Rank <- (nrow(scaled)   1) - rank(scaled$`Performance Score`)
    
    scaled
    
    
  })
  

  observeEvent(input$weight1, {
    freezeReactiveValue(input, "weight2")
    updateNumericInput(session, 'weight2', value = 1 - input$weight1)
  })
  
  output$table1 <- renderDT({
    req(scaled())
    datatable(scaled(), options = list( columnDefs = list(list(
          className = 'dt-center', targets = "_all")),paging = TRUE,searching = FALSE,
        pageLength =  10, dom = 'tip',scrollX = TRUE),rownames = FALSE)
  })

}

shinyApp(ui = ui, server = server)

enter image description here

CodePudding user response:

I think you can make the following small change in the server function

    methods <- list("1" = max, "2" = min)
    funcs = c(methods[[req(input$maxmin1)]], methods[[req(input$maxmin2)]])
  
    scaled <- df1 |>
      mutate(Coverage = funcs[[1]](Coverage) / Coverage,
             Production = Production / funcs[[2]](Production))

Notice that I simply create a named list methods that has two elements, the first being the max function and the second being the min function. I have named this list as you have named the choices in the input$maxmin1 and input$maxmin2 objects. Then I create a vector funcs which simply selects the appropriate matching function from the list. In the next lines, I use funcs[[1]] as the function to apply to Coverage and funcs[[2]] as the function to apply to Production

  • Related