簡體   English   中英

R Shiny SelectizeInput:從分組選項傳遞值不起作用

[英]R Shiny SelectizeInput: Passing values from grouped choices not working

按照此鏈接R shiny selectInput: how to search group name/label中給出的答案,我創建了一個 Shiny 應用程序,示例如下:

編輯請注意 SQLDF 部分代表實際平台中的 MySQL 查詢。 因此,我通常希望將input$Search * 的值傳遞給 MySQL 查詢。

  library(shiny)
  library(tidyverse)
  library(sqldf)
  library(DT)
  library(stringr)

       df <- data.frame(empName = c("Jon", "Bill", "Maria", "Dan", "Ken", "Fay"),
             empID = c("J111", "B222", "M333", "D444", "K555", "F666"),
             empAge = c(23, 41, 32, 28, 35, 38),
             empSalary = c(21000, 23400, 26800, 27200, 30500, 32000),
             empGroup = c("Employee", "Employee", "Manager", "Manager", "Director","Director")
   )


     df$empGroup <- as.factor(as.character(df$empGroup))

    x <- as.vector(levels(df$empGroup))

      groups <- function(x){
                      for(i in 1:length(x)){
                        if(i == 1){
                        savelist <-c()
                       newlist <- list(list(value = x[i], label=x[i]))
                       savelist <- c(savelist, newlist) 
                      }else{
                       newlist <- list(list(value = x[i], label=x[i]))
                           savelist <- c(savelist, newlist) 
                        }
                          }
                     return(savelist)
                       }



           shinyApp(

                  ui = fluidPage(  

                         selectizeInput('Search', NULL, NULL, multiple = TRUE, options = list(
                                       placeholder = 'Select name',
                            # predefine all option groups
                           optgroups = lapply(unique(df$empGroup), function(x){
                            list(value = as.character(x), label = as.character(x))
                             }),
  
           # what field to sort according to groupes defined in 'optgroups'
                 optgroupField = 'empGroup',
  
          # you can search the data based on these fields
               searchField = c('empName', 'empGroup', 'empID'),
  
         # the label that will be shown once value is selected
               labelField= 'empName',
  
         # (each item is a row in data), which requires 'value' column (created by cbind at server side)
              render = I("{
                     option: function(item, escape) {
                 return '<div>' + escape(item.empName) +'</div>';
                        }
                   }")
                 )),
             hr(),
       fluidRow(
            column(6, DT::dataTableOutput("table1")))
            ),

    server = function(input, output, session) {  

                 updateSelectizeInput(session, 'Search', choices = cbind(df, value = 
                                                                    seq_len(nrow(df))), 
                     server = TRUE)


         df1 <- reactive ({ 
              Selected <-df %>% filter(empName %in% input$Search)%>% select(empID)
                    SelectedID<-sapply(Selected, as.character)
                     N<-stringr::str_c(stringr::str_c("'", SelectedID, "'"), collapse = ',')
                    sqldf(paste0("SELECT  empAge, empSalary  
                   FROM df  WHERE  empID IN (",N,")"))
                    })     

      output$table1 = DT::renderDataTable({ 
                    req(input$Search)
               df1()}, options = list(dom = 't'))  
           })

該應用程序在 stri_c(..., sep = sep, collapse = collapse, ignore_null = TRUE): argument is not an atomic vector; 中拋出警告警告; 脅迫

但是,如果我不對 selectizeInput 選擇進行分組,它會像下面的應用程序一樣工作:

   library(shiny)
   library(tidyverse)
   library(sqldf)
   library(DT)
   library(stringr)

   df <- data.frame(empName = c("Jon", "Bill", "Maria", "Dan", "Ken", "Fay"),
             empID = c("J111", "B222", "M333", "D444", "K555", "F666"),
             empAge = c(23, 41, 32, 28, 35, 38),
             empSalary = c(21000, 23400, 26800, 27200, 30500, 32000)
   )


  shinyApp(

     ui = fluidPage(
               selectizeInput( "Search", label = p("Select name"), choices = NULL,
                options = list(  placeholder = 'Select name', maxOptions = 10,
                                 maxItems = 3,  searchConjunction = 'and' )),
               hr(),
                 fluidRow(
          column(6, DT::dataTableOutput("table1")))
               ),

         server = function(input, output, session) {

                    updateSelectizeInput(session,
                     "Search",
                     server = TRUE,
                     choices = df$`empName`)


          df1 <- reactive ({ 
                    Selected <-df %>% filter(empName %in% input$Search)%>% select(empID)
                     SelectedID<-sapply(Selected, as.character)
                    N<-stringr::str_c(stringr::str_c("'", SelectedID, "'"), collapse = ',')
                     sqldf(paste0("SELECT  empAge, empSalary  
                     FROM df  WHERE  empID IN (",N,")"))
                   })     

           output$table1 = DT::renderDataTable({ 
                     req(input$Search)
                     df1()}, options = list(dom = 't'))  
         })

我怎樣才能在 selectizeInput 中有分組的第一個場景中實現相同的 output?

以下是否符合您的要求?

library(shiny)
library(tidyverse)
library(DT)

df <- data.frame(
    empName = c("Jon", "Bill", "Maria", "Dan", "Ken", "Fay"),
    empID = c("J111", "B222", "M333", "D444", "K555", "F666"),
    empAge = c(23, 41, 32, 28, 35, 38),
    empSalary = c(21000, 23400, 26800, 27200, 30500, 32000),
    empGroup = c("Employee", "Employee", "Manager", "Manager", "Director","Director"))
df$empGroup <- as.factor(as.character(df$empGroup))

ui <- fluidPage(
    selectizeInput(
        inputId = 'Search',
        label = NULL,
        choices = NULL,
        multiple = TRUE,
        options = list(
            placeholder = 'Select name',
            # predefine all option groups
            optgroups = lapply(unique(df$empGroup), function(x) {
                list(value = as.character(x), label = as.character(x))
            }),
            # what field to sort according to groupes defined in 'optgroups'
            optgroupField = 'empGroup',
            # you can search the data based on these fields
            searchField = c('empName', 'empGroup', 'empID'),
            # the label that will be shown once value is selected
            labelField= 'empName',
            # (each item is a row in data), which requires 'value' column (created by cbind at server side)
             render = I("{
                    option: function(item, escape) {
                return '<div>' + escape(item.empName) +'</div>';
                       }
                  }")
        )
    ),
    hr(),
    fluidRow(
        column(6, DT::dataTableOutput("table1"))))

server <- function(input, output, session) {
    updateSelectizeInput(
        session = session,
        inputId = 'Search',
        choices = cbind(df, value = seq_len(nrow(df))),
        server = TRUE)

    df1 <- reactive({
        df %>%
            rowid_to_column("idx") %>%
            filter(idx %in% input$Search) %>%
            select(empAge, empSalary)
        })

    output$table1 = DT::renderDataTable({
        req(input$Search)
        df1()
    }, options = list(dom = 't'))
}

shinyApp(server = server, ui = ui)

在此處輸入圖像描述

附言。

我已經稍微清理了你的代碼,因為我發現很難理解/消化你在做什么。 例如,我沒有看到同時使用sqldftidyverse的意義; 如果您已經加載了完整的tidyverse ,您也可以使用dplyr進行所有數據操作/過濾(而不是添加另一個依賴項)。 需要注意的一點是,當您加載stringr時會自動加載tidyverse ,因此無需顯式調用library(stringr) 我刪除了您在這個最小代碼示例中不使用的定義xgroup的行。 我還建議根據流行和公開可用的 R 風格指南之一使用一致的縮進和空格用法。 這將有助於(您和其他人)提高可讀性。


更新

要在sqldf中執行reactive數據過濾,您可以將上面的df1 <- reactive({})塊替換為

library(sqldf)

...

df1 <- reactive({
    data <- transform(df, idx = 1:nrow(df))
    sqldf(sprintf(
        "select empAge, empSalary from data where idx in (%s)",
        toString(input$Search)))
})

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM