1

I am working on a shiny app that has a reactive df which I am using to render a dt data table. My issue is that on my sidebar pickerInput filters I am using:

choices = unique(COLUMN_NAME)

When there is NA values in the column that gets turned into "NA" on the filter so when I use:

filter(COLUMN_NAME %in% input$column_name)

In the reactive df the NA values do not filter correctly. What is the best way around this? Should I recode any NA values to a string or should I work around fixing the sidebar filter so that NA filters to truly NA values?

user3249770
  • 329
  • 2
  • 7
  • Please add a minimum reproducible example so that people can help you. https://stackoverflow.com/help/minimal-reproducible-example – Eli Berkow Nov 04 '22 at 07:41
  • Based on what you have said though, the recoding NA values as characters may be the easiest. – Eli Berkow Nov 04 '22 at 07:47

1 Answers1

0

I think much better would be to leave NA as a special case, i.e. treating it as missing value, not character. This is because in R (and you compute in R) NA is a well-established object, so you may get many advantages (like speed) when leaving it in a data frame as NA (missing value).

But that's true, that JavaScript doesn't have such an construct as NA, so we end up with character type:

jsonlite::toJSON(c(1, NA, 2))
#> [1,"NA",2]

Assuming that:

  • you are working with data.frame (you want to filter data.frame) and you use dplyr::filter (very important as by the default, if you filter by known value, missing values are dropped, different than in e.g. c(1, NA)[c(1, NA) == 1], where NA values will be preserved).

You can try something like this:

library(shiny)
library(dplyr)

is_val <- function(value, set) {
  if (all(value == "NA")) {
    is.na(set)
  } else {
    if (any(value == "NA")) {
      set %in% value | is.na(set)
    } else {
      set %in% value
    }
  }
}

choices <- data.frame(col = c(1, NA, 2, 1, 3, 1, 2))


ui <- fluidPage(
  selectInput("column_name", "Choose", choices = unique(choices$col), multiple = TRUE),
  tableOutput("display_val")
)

server <- function(input, output, session) {
  output$display_val <- renderTable({
    req(input$column_name)
    choices |> 
      filter(is_val(input$column_name, col))
  })
  
}

shinyApp(ui, server)

The crucial is function is_val of course, which has different modes depending of if the "NA" was picked up by user or not. This code could be a little simpler if pickerInput won't have multiple = TRUE.

gss
  • 1,334
  • 6
  • 11