Reputation: 139
It must be late because I can't figure this out. When I run the Shiny app below the DataTable appears blank.
Could you help me spot my mistake please?
As far as I know df_filtered
should return df
if no input is selected. And the it is called as a reactive function by renderDataTable
.
library(shiny)
library(shinydashboard)
library(DT)
library(dplyr)
# Test data
LANZ <- c(1,2,3,4,5)
TIPO <- c('V5', 'V5', 'V10', 'V10', 'V10')
PROY <- c('1', '2', '2', '2', '3')
YEAR <- c(2019, 2020, 2020, 2020, 2019)
df <- data.frame(LANZ, TIPO, PROY, YEAR)
colnames(df)[1] <- "LANZ"
colnames(df)[2] <- "TIPO"
colnames(df)[3] <- "PROY"
colnames(df)[4] <- "YEAR"
ui <- dashboardPage(
dashboardHeader(title = "Title"),
dashboardSidebar(
sidebarMenu(
)),
dashboardBody(
wellPanel(
fluidRow(
column(4, selectInput("idYearD", "", selected=NULL, multiple=FALSE, choice=c('Year' = '', c("2019","2020")))),
column(4, selectInput("idTipo", "", selected=NULL, multiple=FALSE, choice=c('Tipo' = '', c("V5","V10")))),
column(4, selectInput("idProy", "", selected=NULL, multiple=FALSE, choice=c('Proy' = '', c("1","2","3")))
)),
fluidRow(
column(12, DT::dataTableOutput('dataTable'))
))
))
server <- function(input, output) {
df_filtered <- reactive({
data_df <- df
if (!is.null( input$idYearD ) ) {
data_df <- data_df %>% filter(YEAR %in% input$idYearD)
}
if (!is.null( input$idTipo )) {
data_df <- data_df %>% filter(TIPO %in% input$idTipo)
}
if (!is.null( input$idProy )) {
data_df <- data_df %>% filter(PROY %in% input$idProy)
}
data_df
})
output$dataTable <- DT::renderDataTable(
df_filtered()
)
}
shinyApp(ui = ui, server = server)
Best regards.
Upvotes: 1
Views: 295
Reputation: 160862
Up front: is.null
is not catching the fact that input$idYearD
can be (and starts as) the empty string, ""
. Use either !is.null(.) && nzchar(.)
or shiny::isTruthy(.)
.
Side note: input$idYearD
is a string, whereas your YEAR
is a number. R is doing the intuitive thing by inferring the comparison (casting/coercing), but you need to be aware that this is doing a string comparison, not a numeric one. It works here. This is more impactful when dealing with floating-point and/or order of things, as <
and >
(and sort
and order
...) are doing alphabetic comparisons ... "11" < 2
is counter-intuitively true.
What I did was interject browser()
in your df_filtered
reactive block:
df_filtered <- reactive({
browser()
# ...
})
From there, on execution, testing
!is.null( input$idYearD )
# [1] TRUE
input$idYearD
# [1] ""
So perhaps this block instead:
df_filtered <- reactive({
data_df <- df
if ( isTruthy( input$idYearD ) ) {
data_df <- data_df %>% filter(YEAR %in% input$idYearD)
}
if ( isTruthy( input$idTipo ) ) {
data_df <- data_df %>% filter(TIPO %in% input$idTipo)
}
if ( isTruthy( input$idProy ) ) {
data_df <- data_df %>% filter(PROY %in% input$idProy)
}
data_df
})
Alternatively (and more compactly), you could do:
df_filtered <- reactive({
df %>%
filter(
!isTruthy( input$idYearD ) | YEAR %in% input$idYearD,
!isTruthy( input$idTipo ) | TIPO %in% input$idTipo,
!isTruthy( input$idProy ) | PROY %in% input$idProy
)
})
Edited to remove is.null
, since isTruthy(NULL)
is the same as !is.null(NULL)
.
If for some reason in your future isTruthy
doesn't quite meet all of your needs, your original code could be augmented for just a string-specific comparison, as in
if (!is.null( input$idYearD ) && nzchar( input$idYearD )) {
Upvotes: 3