Замена повторяющихся строк в столбце в блестящем

#r #shiny #dt

Вопрос:

У меня есть блестящее приложение, в котором пользователь может выбрать один или несколько анализов в зависимости от типа воды. Они должны иметь возможность выбирать столько анализов, сколько пожелают для каждого типа воды, независимо друг от друга. Например, они должны иметь возможность выбрать 2 анализа в пресной воде и три в морской воде. В этом примере таблица в идеале выглядела бы так:

   Freshwater Saltwater
  <chr>      <chr>    
1 pH         pH       
2 turbidity  salinity 
3 -          turbidity
 

Но у меня возникли проблемы с форматированием моей таблицы, так data.frame как она динамична. Вот воспроизводимый пример:

 library(shiny)
library(shinyWidgets)
library(DT)

AnalysisChoices = c("pH", "salinity","turbidity")

shinyApp(
  ui = fluidPage(box(pickerInput( 
    
    inputId = "anaFW",
    label = "Analysis 2",
    choices =AnalysisChoices,
    
    multiple = T,
    options = list(`actions-box` = TRUE)),
    
    pickerInput(
      
      inputId = "anaSea",
      label = "Analysis 1 ",
      choices = AnalysisChoices,
      multiple = T,
      options = list(`actions-box` = TRUE)))
   ,
    
    
  fluidRow( DT::dataTableOutput ("analysisTbl"),
    style = "  overflow-y: scroll;
                   overflow-x: scroll;"
  ) ),
  
  server = function(input, output) {
    DataAnalysis = reactive({
      df2<- data.frame(
        
        Freshwater = if (length(input$anaFW) == 0) {
          Freshwater = ""
          
        }
        else {
          Freshwater = input$anaFW
          
        },
        SeaWater = if (length(input$anaSea) == 0) {
          SeaWater = ""
        }
        else {
          SeaWater = input$anaSea
        })
      return(list(df2 = (df2)))
      
      
     
   
      
    })
    output$analysisTbl <- renderDataTable({DataAnalysis()$df2})


} )
 

Если у меня есть один анализ в одном из вариантов и несколько в другом варианте, анализ в первом варианте будет повторен в следующих строках. Если я попробую предыдущий пример (2 варианта для одного типа воды и 3 для другого), то я получу сообщение об ошибке, так как функция не будет знать, как заполнить пустые строки. Как я могу заменить пустые ячейки на - ?

Ответ №1:

Возможно, это удовлетворит ваши потребности.

 library(shiny)
library(shinyWidgets)
library(DT)

################ cbind datasets with different number of rows  ######
cbindPad <- function(...){
  args <- list(...)
  n <- sapply(args,nrow)
  mx <- max(n)
  pad <- function(x, mx){
    if (nrow(x) < mx){
      nms <- colnames(x)
      padTemp <- matrix(NA, mx - nrow(x), ncol(x))
      colnames(padTemp) <- nms
      if (ncol(x)==0) {
        return(padTemp)
      } else {
        return(rbind(x,padTemp))
      }
    }
    else{
      return(x)
    }
  }
  rs <- lapply(args,pad,mx)
  return(do.call(cbind,rs))
}

AnalysisChoices = c("pH", "salinity","turbidity")

shinyApp(
  ui = fluidPage(box(pickerInput( 
    
    inputId = "anaFW",
    label = "Analysis 2",
    choices =AnalysisChoices,
    
    multiple = T,
    options = list(`actions-box` = TRUE)),
    
    pickerInput(
      
      inputId = "anaSea",
      label = "Analysis 1 ",
      choices = AnalysisChoices,
      multiple = T,
      options = list(`actions-box` = TRUE)))
    ,
    
    
    fluidRow( DT::dataTableOutput ("analysisTbl"),
              style = "  overflow-y: scroll;
                   overflow-x: scroll;"
    ) ),
  
  server = function(input, output) {
    DataAnalysis = reactive({
      df1<- data.frame(
        Freshwater = if (length(input$anaFW) == 0) {
          Freshwater = ""
        }
        else {
          Freshwater = input$anaFW
        })
      
      df2 <- data.frame(
        SeaWater = if (length(input$anaSea) == 0) {
          SeaWater = ""
        }
        else {
          SeaWater = input$anaSea
        })
      
      df <- cbindPad(df1,df2)
      return(df)
      
    })
    
    output$analysisTbl <- renderDataTable({DataAnalysis()})
    
  } )
 

выход