如何在R Shiny中构建动态过滤器?

时间:2016-09-13 08:06:06

标签: r shiny shiny-reactivity

我正在构建一个带有上传功能和类别变量过滤功能的应用程序。这样,用户就可以通过指定列和值来进行一些数据操作。但是,过滤功能不起作用。代码简化如下:

#ui.R
library(shiny)

fluidPage(
  titlePanel("Test Dynamic Column Selection"),
  sidebarLayout(
    sidebarPanel(
      fileInput('file1', 'Choose CSV File',
            accept=c('text/csv', 
                     'text/comma-separated-values,text/plain', 
                     '.csv')),
      hr(),
      checkboxInput('header', 'Header', TRUE),
      radioButtons('sep', 'Separator',
               c(Comma=',',
                 Semicolon=';',
                 Tab='\t'),
               ','),
      hr(),
      uiOutput("choose_columns"),
      hr(),
      uiOutput("choose_column"),
      textInput('column_value', label = 'Value'),
      actionButton('filter', label = 'Filter')
    ),
    mainPanel(
      tableOutput('contents')
    )
  )
)

#server.R
library(shiny)

function(input, output) {

  uploaded_data <- reactive({
    inFile <- input$file1
    read.table(inFile$datapath, header=input$header, sep=input$sep, quote=input$quote)
  })

  react_vals <- reactiveValues(data = NULL)

  output$choose_columns <- renderUI({
    if(is.null(input$file1))
      return()

    colnames <- names(react_vals$data)

    checkboxGroupInput("choose_columns", "Choose columns", 
                   choices  = colnames,
                   selected = colnames)
  })

  output$choose_column <- renderUI({
    if(is.null(input$file1))
      return()
    is_factor <- sapply(react_vals$data, is.factor)
    colnames <- names(react_vals$data[, is_factor])
    selectInput("choose_column", "Choose column", choices = colnames)
  })

  observeEvent(input$file1, react_vals$data <- uploaded_data())
  observeEvent(input$choose_columns, react_vals$data <- react_vals$data[, input$choose_columns])

  # This line of code does not work :(
  observeEvent(input$filter, react_vals$data <- subset(react_vals$data, input$choose_column != input$column_value))

  output$contents <- renderTable(react_vals$data)
}

1 个答案:

答案 0 :(得分:2)

我认为您的应用存在多个问题,我尝试逐步解释:

  1. input$choose_columns取决于react_vals$data被动值,因此当取消选中一个复选框时,Shiny会为react_vals$data分配一个新值,少一列,然后重新呈现{{1 UI,因此可用的复选框少了一个。 (与input$choose_columns input$choose_column
  2. 相同

    您的代码:

      

    selectInput

    替换码:

    colnames <- names(react_vals$data)
    1. 在检查文件是否已上传,是否呈现UI等时使用colnames <- names(uploaded_data()) 。这是最佳做法。
    2. 您的代码:

        

      req()

      替换码:

      if(is.null(input$file1)) return()
      1. 过滤无效。基本上它为什么不起作用的是它尝试根据比较来自req(input$file1) input$choose_column的两个字符串进行子集化。
      2. ,即:“列名A”!=“价值:某事”

        通常会为每一行返回input$column_value,并且最终根本不会过滤。

        我想出了两个解决方案,它们有点难看,所以如果有人想出更好的解决方案,请随时评论/编辑。

        TRUE