Search code examples
rshinyggvis

Filter Data Range based on User Input


I have a shiny app that plots two variables in a scatter plot and filters based on user input. I am trying to get it so that the user can filter the data based on a range that they specify. However, I only want this filter to be applied if the field is filled out, and return to all data if the field is empty (null). For example, if you launch the code that I have attached, I want the user to be able to check the Specify Data Ranges checkbox and when they put in 4.8 in the min x input box, the data is filtered out so that no data points less than 4.8 are now considered. The sample code that I have prepared is below with my attempt at what I'm trying to do commented out near the middle.

#Check packages to use in library
{
library('shiny') #allows for the shiny app to be used
library('ggvis') #allows for interactive ploting
}

alldata <- iris

#establish options for drop down menus
{
specieschoices <- unique(as.character(alldata$Species))
}
# UI

ui<-fluidPage(
titlePanel("Explorer"),
fluidRow(
column(4,
       wellPanel(
         h4("Apply Filters"),
         selectInput(inputId = "species", label="Select a Species:", choices = sort(specieschoices), selected="setosa", multiple = TRUE, selectize = TRUE)
       )),
column(8,
       ggvisOutput("plot1")
),
column(4,
       wellPanel(
         h4("Data Variables"),
         selectInput(inputId = "x", label="Select x-axis Variable:", choices=as.character(names(alldata[,1:4])),selected='Petal.Length', multiple = FALSE),
         selectInput(inputId = "y", label="Select y-axis Variable:", choices=as.character(names(alldata[,1:4])),selected='Petal.Width', multiple = FALSE)
       )),

column(4,
       wellPanel(
         checkboxInput(inputId = "datarange", label="Specify Data Ranges", value = FALSE),
         conditionalPanel(
           condition = "input.datarange == true",
           wellPanel(
             numericInput(inputId = "minxdata", label="Specify x axis min", value = -9999999999, step = 0.1),
             numericInput(inputId = "maxxdata", label="Specify x axis max", value = 9999999999, step = 0.1),
             numericInput(inputId = "minydata", label="Specify y axis min", value = -9999999999, step = 0.1),
             numericInput(inputId = "maxydata", label="Specify y axis max", value = 9999999999, step = 0.1)
           ))
       ))
))

#SERVER
server<-function(input,output,session)
{

#Set up reactive variables for ranges
filteredData <- reactive({

minX <- input$minxdata
maxX <- input$maxxdata
minY <- input$minydata
maxY <- input$maxydata

# Apply filters
m <- alldata %>% filter(
  `Species` %in% input$species

  ###############THIS IS THE PART THAT I NEED HELP WITH
  #This works as hardcoded with hypothetical user input of x=Petal.Length and y=Petal.Width
  ,
  Petal.Length >= minX,
  Petal.Length <= maxX,
  Petal.Width >= minY,
  Petal.Width <= maxY

  #This is does not work
  # ,
  # as.symbol(input$x) >= minX,
  # as.symbol(input$x) <= maxX,
  # as.symbol(input$y) >= minY,
  # as.symbol(input$y) <= maxY
  #####################################################

)
m <- droplevels(as.data.frame(m))
m
})

vis <- reactive({

#Plot Data with Visualization Customization
xvar <- prop("x", as.symbol(input$x))
yvar <- prop("y", as.symbol(input$y))

p1 = filteredData() %>%
  ggvis(x = xvar, y = yvar) %>%
  layer_points() %>%

  # Specifies the size of the plot
  set_options(width = 800, height = 450, duration = 0)
})

#Actually plots the data
vis %>% bind_shiny("plot1")
}

#Run the Shiny App to Display Webpage
shinyApp(ui=ui, server=server)

UPDATE:

I think I'm on the right track with this, but the min x and min y filters out all data if changed to anything >= 0, and the other filters do not do anything if changed.

  paste0("`", input$x, "`") >= minX,
  paste0("`", input$x, "`") <= maxX,
  paste0("`", input$y, "`") >= minY,
  paste0("`", input$y, "`") <= maxY

Solution

  • I have discovered an answer based on this completely unrelated post that approached how they processed data in a different way that worked for me. Downloading png from Shiny (R)

    The only change is within filteredData which is posted below.

    #Set up reactive variables for ranges
    filteredData <- reactive({
    
    minX <- input$minxdata
    maxX <- input$maxxdata
    minY <- input$minydata
    maxY <- input$maxydata
    a <- which(names(alldata)==input$x)
    xvariable <- as.numeric(alldata[,a])
    b <- which(names(alldata)==input$y)
    yvariable <- as.numeric(alldata[,b])
    
    # Apply filters
    m <- alldata %>% filter(
    `Species` %in% input$species,
    xvariable >= minX,
    xvariable <= maxX,
    yvariable >= minY,
    yvariable <= maxY
    )
    m <- droplevels(as.data.frame(m))
    m
    })