【问题标题】:DT proxy displays no dataDT 代理显示无数据
【发布时间】:2021-09-24 17:58:45
【问题描述】:

我正在尝试构建的应用程序出现问题。我有一个大型数据表(如下所示的部分),我试图根据用户输入进行过滤。侧面板允许用户选择仪表、日期范围,然后选择所需的列(即沉淀和温度)。如果选择了列复选框,则会显示过滤器选项,允许过滤行。一旦用户单击提交按钮,表格应根据所有选择的输入呈现。当我加载应用程序时会呈现整个数据表,但是一旦我选择了过滤器然后单击提交,表输出会显示“表中没有可用数据”“显示 0 到 0 个条目,共 0 个条目”。应该有数据显示,因为我尝试的值在其中。也许我不应该使用代理表来过滤?我不希望每次更改过滤器时都更新表(因为它是一个大数据集),只是在按下提交按钮时。任何帮助将不胜感激。

# load libraries
library(tidyverse)  
library(DT)
library(rgdal)
library(shiny)
library(shinyjs) #shiny java script with R language
library(here)

# import dataset
allvarsdata = readRDS(here("Scripts/shiny app/allvarsdata.RDS")) #datatable
varsdata = as_tibble(allvarsdata)

A tibble: 6 x 4
  GaugeID     DATE          PRCP  TAIR   
  <chr>     <date>       <dbl>  <dbl> 
1 01013500   1980-10-01    3.1    3.1   
2 01435762   1980-10-02    4.24  10.5 
3 01837490   1980-10-03    8.02  11.8  
4 02947591   1980-10-04   15.3    7.38 
5 03048601   1980-10-05    8.48   4.8 
6 09385031   2014-12-06    0      5.41 



###############################################
ui = fluidPage(
  # implement shiny js features
  useShinyjs(), 
  titlePanel(),  
  tabsetPanel(        
    tabPanel(title = "Data",
             sidebarLayout(
               sidebarPanel(
                 
                 # gauge selection, pull down with all 671 gauges        
                 selectInput(inputId = "gauge1", label = "Select USGS Gauge(s)", 
                             choices = sort(unique(allvarsdata$GaugeID)), 
                             selected = NULL, multiple = TRUE),  
               
                 # two buttons to 1) select all gauges and 2) clear the selections  
                 fluidRow(
                   column(width = 6, actionButton("selectall", "Select all")),
                   column(width = 6, actionButton("clear", "Clear"))
                 ), #fluidRow close
     
# date range selection for entire record
                 dateRangeInput(inputId = "daterange", label = "Select date range", 
                                start = "1981-01-01", end = "2014-12-31", 
                                min = "1981-01-01", max = "2014-12-31",
                                format = "yyyy-mm-dd", separator = " - "), 
                
 # checkbox to select precipitation column          
                 checkboxInput(inputId = "prcp", label = "Precipitation", value = FALSE),  
                 conditionalPanel( #display slider when box checked, filter rows based on slider
                   condition = "input.prcp",
                   sliderInput(inputId = "prcp1", label = "mm/day", 
                                      min = 0, max = 200, value = c(50, 100), ticks = FALSE)),
            
                 checkboxInput(inputId = "temp", label = "Temperature", value = FALSE),
                  conditionalPanel(
                    condition = "input.temp",
                  sliderInput(inputId = "temp1", label = "Celcius", 
                                      min = -45,  max = 40, value = c(0, 20), ticks = FALSE)), 
                 
              # submit button to filter/select data based on all user inputs, only when clicked            
                actionButton(inputId = "submit1", 
                              label = "Submit")
             
                   ), #sidebarPanel close
                 
              mainPanel(
               DT::DTOutput(outputId = "filteredtable")
                 
               ) #mainPanel close 
       )  # sidebarLayout close               
    ), #tabPanel close
   ) # tabsetPanel close   
) # fluidPage close

### SERVER ###

server = function(input, output, session) {
  # create reactive values based on allvarsdata 
  filtered = reactiveValues(fdat = varsdata)
  
  output$filteredtable = DT::renderDT({
   isolate(filtered$fdat)   # render DT with no dependency between data and render function
  }, options = list(paging = TRUE, processing = TRUE))
    
  proxy = DT::dataTableProxy("filteredtable") #updates data instead of using render function
  observe({
   DT::replaceData(proxy, filtered$fdat)
  })
    
 observeEvent(input$submit1, {     #wrap all filters within the submit action button
     filtered$fdat = filtered$fdat %>% 
     dplyr::filter(GaugeID == input$gauge1,
                  DATE >= input$daterange[1], DATE <= input$daterange[2], 
                  PRCP >= input$prcp1[1], PRCP <= input$prcp1[2],  
                  TAIR >= input$temp1[1], TAIR <= input$temp1[2]) 
                 
# if no gauge is selected, return no results      
      if(is.null(input$gauge1)) {
           return(NULL)
       }
     if(is.null(input$prcp)) { # if precip box is not checked, remove precip column     
       filtered$fdat = filtered$fdat %>% 
         select(-PRCP)
            }
     if(is.null(input$temp)) {  # if temp box is not checked, remove temp column from data table    
       filtered$fdat = filtered$fdat %>% 
         select(-TAIR)
     }  
     
    filtered$fdat
     
   }) #observeEvent close (submit)
  
    # clear selected gauges button based on shinyjs reset function      
  observeEvent(input$clear, {
    reset("gauge1")
  })
 
  # select all gauges button 
  observeEvent(input$selectall, {
    if(input$selectall) {
      updateSelectInput(session = session, "gauge1",
                        selected = varsdata$GaugeID) 
    }
  })
      
} # server close bracket

# Run the application
shinyApp(ui = ui, server = server)

reprex package (v2.0.0) 于 2021 年 7 月 15 日创建

【问题讨论】:

    标签: r shiny dt


    【解决方案1】:

    您在过滤时遇到了一些问题。

    1. 你的日期很个性
    2. 变量input$prcpinput$temp 是合乎逻辑的
    3. 即使变量不存在,也会执行过滤(对于temp1prcp1

    一旦你解决了这些问题,你就不需要代理了,因为你的对象是一个reactiveValues 对象。试试这个

    varsdata <- read.table(text="GaugeID     DATE          PRCP  TAIR 
    1 01013500   1980-10-01    3.1    3.1   
    2 01435762   1980-10-02    4.24  10.5 
    3 01837490   1980-10-03    8.02  11.8  
    4 02947591   1980-10-04   15.3    7.38 
    5 03048601   1980-10-05    8.48   4.8 
    6 09385031   2014-12-06    0      5.41",  header=T)
    
    allvarsdata <- varsdata
    
    ###############################################
    ui = fluidPage(
      # implement shiny js features
      useShinyjs(), 
      #titlePanel(),  
      tabsetPanel(id = "tabs",      
        tabPanel(title = "Data", 
                 sidebarLayout(
                   sidebarPanel(
                     
                     # gauge selection, pull down with all 671 gauges        
                     selectInput(inputId = "gauge1", label = "Select USGS Gauge(s)", 
                                 choices = sort(unique(allvarsdata$GaugeID)), 
                                 selected = NULL, multiple = TRUE),  
                     
                     # two buttons to 1) select all gauges and 2) clear the selections  
                     fluidRow(
                       column(width = 6, actionButton("selectall", "Select all")),
                       column(width = 6, actionButton("clear", "Clear"))
                     ), #fluidRow close
                     
                     # date range selection for entire record
                     dateRangeInput(inputId = "daterange", label = "Select date range", 
                                    start = "1980-01-01", end = "2014-12-31", 
                                    min = "1980-01-01", max = "2014-12-31",
                                    format = "yyyy-mm-dd", separator = " - "), 
                     
                     # checkbox to select precipitation column          
                     checkboxInput(inputId = "prcp", label = "Precipitation", value = FALSE),  
                     conditionalPanel( #display slider when box checked, filter rows based on slider
                       condition = "input.prcp",
                       sliderInput(inputId = "prcp1", label = "mm/day", 
                                   min = 0, max = 200, value = c(0, 100), ticks = FALSE)),
                     
                     checkboxInput(inputId = "temp", label = "Temperature", value = FALSE),
                     conditionalPanel(
                       condition = "input.temp",
                       sliderInput(inputId = "temp1", label = "Celcius", 
                                   min = -45,  max = 40, value = c(0, 20), ticks = FALSE)), 
                     
                     # submit button to filter/select data based on all user inputs, only when clicked            
                     actionButton(inputId = "submit1",  label = "Submit")
                     
                   ), #sidebarPanel close
                   
                   mainPanel(
                     DTOutput(outputId = "filteredtable")
                     
                   ) #mainPanel close 
                 )  # sidebarLayout close               
        ) #tabPanel close
      ) # tabsetPanel close   
    ) # fluidPage close
    
    ### SERVER ###
    
    server = function(input, output, session) {
      # create reactive values based on allvarsdata 
      filtered = reactiveValues(fdat = varsdata)
      
      output$filteredtable = renderDT({
        filtered$fdat  # render DT with no dependency between data and render function
      }, options = list(paging = TRUE, processing = TRUE))
      
      # proxy = DT::dataTableProxy("filteredtable") #updates data instead of using render function
      # observe({
      #   DT::replaceData(proxy, filtered$fdat)
      # })
      
      fdata <- eventReactive(input$submit1, {     
        # if no gauge is selected, return no results      
        if(is.null(input$gauge1)) {
          filteredt <- NULL
        }else{
          filteredt = varsdata %>% 
            dplyr::filter(GaugeID %in% input$gauge1, as.Date(DATE) >= as.Date(input$daterange[1]), as.Date(DATE) <= as.Date(input$daterange[2]))
          if(input$prcp) { # if precip box is not checked, remove precip column
            filteredt = filteredt %>% dplyr::filter(PRCP >= input$prcp1[1], PRCP <= input$prcp1[2])
          } else {
            filteredt = filteredt %>% select(-PRCP)
          }
    
          if(input$temp) {  # if temp box is not checked, remove temp column from data table
            filteredt = filteredt %>% dplyr::filter(TAIR >= input$temp1[1], TAIR <= input$temp1[2])
          }else {
            filteredt = filteredt %>% select(-TAIR)
          }
        }
        
        filteredt
      })
      
      observeEvent(input$submit1, { 
        filtered$fdat <- fdata()
      }) #observeEvent close (submit)
      
      # clear selected gauges button based on shinyjs reset function      
      observeEvent(input$clear, {
        reset("gauge1")
      })
      
      # select all gauges button 
      observeEvent(input$selectall, {
        if(input$selectall) {
          updateSelectInput(session = session, "gauge1",
                            selected = varsdata$GaugeID) 
        }
      })
      
    } # server close bracket
    
    # Run the application
    shinyApp(ui = ui, server = server)
    

    【讨论】:

    • 感谢您的帮助!只是一个问题,在UI中添加DTOutput("t1")的目的是什么?
    • 你可以忽略它。我在测试时使用它。
    猜你喜欢
    • 1970-01-01
    • 2018-04-01
    • 2017-11-06
    • 1970-01-01
    • 2018-07-13
    • 1970-01-01
    • 1970-01-01
    • 2019-03-28
    • 2022-07-07
    相关资源
    最近更新 更多