Как динамически обновить выбор выбранного входа в r блестящий - PullRequest
0 голосов
/ 12 июня 2018

Я разрабатываю блестящее приложение, в котором варианты выбора входных данных должны динамически обновляться на основе более ранних входных данных.

Например, если и категория, и сегмент выбраны в первых виджетах ввода, и только skin_care во вторых виджетах ввода, а затем Medicatedи Non-medicated должен присутствовать в качестве опции в 3-х входных виджетах, а не во всех уникальных именах сегментов.Если во 2-х виджетах ввода вместо «skin_care» выбрано «hair_care», то в выпадающем списке «3-х виджетов» следует выбрать «Гентский и женский».Таким образом, в основном выбор из выпадающего списка зависит от того, что выбрал пользователь из предыдущих виджетов ввода.То же самое касается бренда.Здесь я предполагаю, что выбор размерности всегда слева направо.

Фактическое приложение попросит пользователя загрузить данные, и оно может иметь 10 измерений или может быть больше. Я оставил три для простоты.

library(shiny)
library(DT)

ui <- shinyUI(fluidPage(
tabsetPanel(
tabPanel("Data", fluid = TRUE,
         sidebarLayout(
           sidebarPanel(p("Please remove None first"),
                        uiOutput("dim"),
                        uiOutput("levels1")),
           mainPanel(
             DT::dataTableOutput("data_display")
           ))))))

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

# creating Data 
data <- reactive({
data <-  data.frame(Date = as.Date(c("2018-05-25","2018-05-26")),
            category = c(rep("skin_care",6),rep("hair_care",6)),
            Segment =  c(rep("Medicated",4),rep("Non_Medicated",2),
                       rep("Ladies",4),rep("Gents",2)),
            Brand = c("X","X","Y","Y","Z","Z","A","A","B","B","C","C"),
            sales = round(rnorm(12,100,3)))
})


# Displaying Data  

output$data_display <- DT::renderDataTable(                    
datatable(data(),options = list(pageLength = 12),rownames = FALSE)
)

# selects dimension (Only character variable to be selected)

output$dim<-renderUI({
b<-colnames(data()[sapply(data(),class)=="character"])
selectInput("x","Select only character variable",choices = 
              c("NONE",b[1:length(b)]),selected="NONE",multiple = TRUE)
 })

 #  user selects levels of dimension 

output$levels1<-renderUI({
if(is.null(input$x)){
  return(NULL)
}
else if(sum(input$x=="NONE")==1){
  return(NULL)
}
else{
  lapply(seq(input$x),function(i){
    selectInput(inputId = paste0("range",i),
                paste0("Select level of ",input$x[i]),
                choices = c(unique(data()[,input$x[i]]),"ALL"),multiple = TRUE)

   })
  }
 })
 })
shinyApp(ui,server)

РЕДАКТИРОВАТЬ: Предоставляется опция в раскрывающемся списке динамически появляющихся виджетов selectinput

1 Ответ

0 голосов
/ 13 июня 2018

Я играл с кодом, который вы предоставили.Этот ответ может показаться неполным, но я считаю, что это лучший способ решить ваши вопросы.Давайте пройдемся по нему:

  1. В пользовательской части я добавил еще один uiOutput -обёртку с именем level3 (который возвращает раскрывающийся список, только если в самом первом раскрывающемся списке выбрано более одного входа)
  2. Впоследствии я добавил еще одну renderUI в серверную часть
  3. Я переместил DT -таблицу в конец серверной части
  4. Я добавил полный наборусловий if-else к levels1 -объекту в серверной части (слишком сложно объяснить, просто попробуйте их)
  5. Я также добавил полный набор условий if-else, чтобы проверить, является липользовательский интерфейс работает

Однако я не понимаю, как сохранить общий код в своем ответе.Я имею в виду, если у вас есть несколько столбцов, может быть проще сделать раскрывающийся список для каждого столбца.Кажется проще для меня

Основная проблема заключается в том, что вы не можете угадать , какой элемент пользователь выберет первым в первом раскрывающемся списке.Поэтому вам нужно будет пройти через все возможные комбинации.Который чокнутый, если у вас есть более двух переменных.В любом случае, потому что вы знаете данные, которые вы знаете лучше меня, если дополнительные усилия по программированию стоят времени.Если вы мне не верите, используйте мой код, попробуйте обобщить код, используйте пять столбцов, а затем прокомментируйте ниже то, что вы узнали.

Последнее, но не менее важное: я часто использовал grep для поднабора данных.Если вы объедините это с paste и collapse='|', это будет соответствовать каждому случаю вашего вектора персонажа.

Вот приложение:

library(shiny)
library(DT)

ui <- shinyUI(fluidPage(
  tabsetPanel(
    tabPanel("Data", fluid = TRUE,
             sidebarLayout(
               sidebarPanel(uiOutput("dim"),
                            uiOutput("levels1"),
                            uiOutput("level3")),
               mainPanel(
                 DT::dataTableOutput("data_display")
               ))))))

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

  # creating Data 
  data <- reactive({
    data <-  data.frame(Date = as.Date(c("2018-05-25","2018-05-26")),
                        category = c(rep("skin_care",6),rep("hair_care",6)),
                        Brand = c("X","X","Y","Y","Z","Z","A","A","B","B","C","C"),
                        sales = round(rnorm(12,100,3)),stringsAsFactors = FALSE)
  })




  # selects dimension (Only character variable to be selected)

  output$dim<-renderUI({
    b<-colnames(data()[sapply(data(),class)=="character"])
    selectInput("x","Select only character variable",
                choices = b[1:length(b)],multiple = TRUE)
  })


  #  user selects levels of dimension 
  output$levels1<-renderUI({
    if(is.null(input$x)){
      return(NULL)
    }
    else if(sum(input$x=="NONE")==1){
      return(NULL)
    }
    else{
      mydata<-data()
      if(length(input$x)==2){
        selectInput(inputId = 'range1',
                    paste0("Select level of ",'category'),
                    choices = unique(as.character(mydata$category)),
                    selected = "",multiple = TRUE)
      } else {
        lapply(seq(input$x),function(i){
          mychoice<-unique(as.character(mydata[,input$x[i]]))
          selectInput(inputId = paste0("range",i),
                      paste0("Select level of ",input$x[i]),
                      choices = mychoice,selected = "",multiple = TRUE)
          })
      }
    }
  })

  output$level3<-renderUI({
    if(is.null(input$range1) | length(input$x)<2){
      return(NULL)
    } else {
      mydata<-data()
      myrows<-grepl(paste0(input$range1,collapse = '|'),mydata$category)
      mychoices<-unique(as.character(mydata$Brand[myrows]))
      selectInput(inputId = 'range2',
                  paste0("Select level of ",'category'),
                  choices = mychoices,
                  selected = mychoices,multiple = TRUE)
    }

  })

  # Displaying Data  

  output$data_display <- DT::renderDataTable({
    if(is.null(input$x)){ #show full data when nothing is selected in first dropdown
      mydata<-data()
    }
    if(is.null(input$range1)){ # show full data when nothing is selected in second drop down
      mydata<-data()
    } else { # something is selected in second dropdown
      if(length(input$x)>1){ # First dropdown contains two elements
        mydata<-data()
        if(!is.null(input$range2)){
          mydata=mydata[grep(paste0(input$range2,collapse='|'),as.character(mydata$Brand)),]
        }
      } else { # First dropdown contains one element
        mydata<-data()
        if(input$x=='Brand'){
          mydata=mydata[grep(paste0(input$range1,collapse='|'),as.character(mydata$Brand)),]
        } else{
          mydata=mydata[grep(paste0(input$range1,collapse='|'),as.character(mydata$category)),]
        }
      } # close: First dropdown has one element
    } # close: something is selected in second dropdown


    datatable(mydata,options = list(pageLength = 12),rownames = FALSE)
  })


  # observeEvent(input$x,
  #              updateSelectInput(inputId = paste0("range",i),
  #                                paste0("Select level of ",input$x[i]),
  #                                choices = unique(data()[,input$x])))

})

shinyApp(ui,server)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...