8

I use Shiny with the likert-library, which outputs ggplot2 objects, to display answer distributions interactively. The user can choose which group of questions to plot (each group has various numbers of questions), and which question to group by. This means that in total there is a big variety in the number of "bars" showing up.

If I leave the height setting on auto (default), the graph becomes impossibly crowded.

enter image description here

There seems to be two ways to adjust height - in ui.R, I can adjust the size of the "viewport", and in the call to renderPlot, I can specify the height of the graph (if it is higher than the viewport, there is a scrollbar). If I specify a roomier graph, the graph above looks great:

enter image description here

However, when I go back to a question with fewer alternatives, they become stretched out to look ridiculous:

enter image description here

Is there a way to get the bars to have a constant width, no matter how many of them there are, and for the graph to resize dynamically without me having to calculate the specific height depending on number of elements?

2
  • 1
    Are you just talking about the graphics device window in R or Rstudio? Or are you saving these to disc somehow? A "plot" doesn't have any height really, it just fills the device you render it to. So you need to share the code you're using to actually draw the plots. Are you using renderPlot or something? Commented Sep 9, 2014 at 21:06
  • 1
    In Shiny, I'm using renderPlot, either with no specific height, or with height=900. Commented Sep 12, 2014 at 15:50

1 Answer 1

6

To my current knowledge, their is no default way to have renderPlot({}) "find" the right height for your ggplot object (or for any other R plot object) "automatically". The "right" height is somewhat subjective, so you would have to manually calculate the height yourself. There might be packages out there that attempts to do this, but even if such thing exists, I think you prefer to create your own custom "algorithm" to find the right height. As for many cases, this algorithm simply depends on number of facet groupings that is creating that cramped feel in your plot. Simply do:

output$myPlotOutput <- renderPlot({
  myGGPlotCode
}, height = myHeightAlgorithm())

Where myHeightAlgorithm() returns a number for height in pixels (see ?renderPlot() height argument.

However, the above solution is something that you can easily find in Shiny documentation. From my experience what you should do is use the following "algorithm"

set_shiny_plot_height <- function(session, output_width_name){
   function() { 
     session$clientData[[output_width_name]] 
   }
}

Where session is the session argument in shinyServer(function(input, output, session)) and output_width_name is the name of the output$myPlotOutput width. The name of the output$myPlotOutput's width's session name is : output_myPlotOutput_width

i.e. you should use set_shiny_plot_height(session, "output_myPlotOutput_width") in place of myHeightAlgorithm()

Ultimately, the above code will create a square plot (since my height is equal to the width). However, I suggest extracting the width and incorporating your height algorithm to take consideration of the width of the plot output. You should always make your objects responsive to changes in width for web applications.

set_shiny_plot_height_with_respects_to_width <- function(session, output_width_name){
   width <- function() { 
     session$clientData[[output_width_name]] 
   }
   # Do something with the width
   width / 2
}
Sign up to request clarification or add additional context in comments.

2 Comments

This is awesome thanks! How can I react to changes in the width?
Answer: session$clientData$output_myPlotOutput_width can be used as a reactive variable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.