Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to automatically "right-size" ggplot in Shiny?

Tags:

r

ggplot2

shiny

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?

like image 841
Stian Håklev Avatar asked Sep 09 '14 19:09

Stian Håklev


1 Answers

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
}
like image 64
BetweenTwoTests Avatar answered Oct 31 '22 02:10

BetweenTwoTests