Search code examples
rshinyggvis

add axis only if user specifies range


I am trying to get a shiny app to specify the axis range if the user changes the default values. As of now, the user can filter the data based on a specified value (filter is always active which is why the defaults are such extreme values), but I want to provide the functionality to also specify the axis range as that same value.

The sample code is my attempt at doing this, but I would also like to be able to have the axis be default for the max value if they only specify a min value (in the 2nd image, this would mean that the axis would have a minimum of 3 and a max set by the default. I realize that is the case in the example I provided, but I want the user to be able to set the min to -2 and have the axis expand to see white space out to x=-2 with the max still set at the default) and I am not sure how to begin constructing that.

#Check packages to use in library
{
library('shiny') #allows for the shiny app to be used. I am using V0.13.1
library('ggvis') #allows for interactive ploting. I am using V0.4.2
library('dplyr') #I am using V0.4.3
}

alldata <- iris

#establish options for drop down menus
{
specieschoices <- unique(as.character(alldata$Species))
petalwchoices <- unique(as.character(alldata$Petal.Width))
petallchoices <- unique(as.character(alldata$Petal.Length))
sepallchoices <- unique(as.character(alldata$Sepal.Length))
sepalwchoices <- unique(as.character(alldata$Sepal.Width))
}
# UI

ui<-fluidPage(
titlePanel("Explorer"),
fluidRow(
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(
             wellPanel(
               numericInput(inputId = "minxaxis", label="Specify x axis min", value = -999999999),
               numericInput(inputId = "maxxaxis", label="Specify x axis max", value = 999999999),
               numericInput(inputId = "minyaxis", label="Specify y axis min", value = -999999999),
               numericInput(inputId = "maxyaxis", label="Specify y axis max", value = 999999999)
             )
         ))
))

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

#Set up reactive variables
filteredData <- reactive({
  minX <- input$minxaxis
  maxX <- input$maxxaxis
  minY <- input$minyaxis
  maxY <- input$maxyaxis
  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(
  xvariable >= minX,
  xvariable <= maxX,
  yvariable >= minY,
  yvariable <= maxY
)
m <- droplevels(as.data.frame(m))
m
})

vis <- reactive({

xvar <- prop("x", as.symbol(input$x))
yvar <- prop("y", as.symbol(input$y))
minX <- input$minxaxis
maxX <- input$maxxaxis
minY <- input$minyaxis
maxY <- input$maxyaxis

p1 = filteredData() %>%
  ggvis(x = xvar, y = yvar) %>%
  layer_points(size.hover := 200,
               fillOpacity:= 0.5, fillOpacity.hover := 1
  ) %>%

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


#################### THIS IS THE PART THAT I NEED HELP ON ####################### 
# %>%>
# if (minX != -999999999 & maxX != 999999999) {
#   add_axis("x", values = minX:maxX)
# }
# else if (minY != -999999999 & maxY != 999999999) {
#   add_axis("y", values = minY:maxY)
# }
#################################################################################

})

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

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

default view of program

Min x axis changed to 3


Solution

  • You can set your axis limits to either NA or the chosen value using a logic statement and the input value, e.g., input$minxaxis.

    minX = if(input$minxaxis == -999999999) {NA} else {input$minxaxis}
    maxX = if(input$maxxaxis == 999999999) {NA} else {input$maxxaxis}
    minY = if(input$minyaxis == -999999999) {NA} else {input$minyaxis}
    maxY = if(input$maxyaxis == 999999999) {NA} else {input$maxyaxis}
    

    Then you can use scale_numeric to set the limits of the axes via domain. If one of the limits is NA then the default domain value is used instead.

    p1 = filteredData() %>%
        ggvis(x = xvar, y = yvar) %>%
        layer_points(size.hover := 200,
                   fillOpacity:= 0.5, fillOpacity.hover := 1) %>%
        scale_numeric("x", domain = c(minX, maxX), clamp = TRUE) %>%
        scale_numeric("y", domain = c(minY, maxY), clamp = TRUE)