11
votes

Consider this simple ggplot:

enter image description here

I drew a black edge on it, so it's easier to envision how large it is.

I don't understand why this plot is so large. There is nothing in my code telling ggplot that I want any area above or beneath the plot.

This seems to get me every time. How can I control the canvas size in ggplot?

library(ggplot2)

hex=c("#CC0000", "#90BD31", "#178CCB")    

q <- ggplot(data=NULL)
    q <- q + geom_rect(data=NULL, aes(xmin=0, xmax=1, ymin=0.5, ymax=1.5), fill=hex[1])
    q <- q + geom_rect(data=NULL, aes(xmin=1.5, xmax=2.5, ymin=0.5, ymax=1.5), fill=hex[2])
    q <- q + geom_rect(data=NULL, aes(xmin=3, xmax=4, ymin=0.5, ymax=1.5), fill=hex[3])
    q <- q + annotate("text", x=.5, y=0.1, label='Impaired', size=4)
    q <- q + annotate("text", x=2, y=0.1, label='Normal', size=4)
    q <- q + annotate("text", x=3.5, y=0.1, label='Optimal', size=4)
    q <- q + coord_fixed()
    q <- q + theme_classic()
    q <- q + theme(axis.line=element_blank(),
                   axis.text.x=element_blank(),
                   axis.text.y=element_blank(),
                   axis.ticks=element_blank(),
                   axis.title.x=element_blank(),
                   axis.title.y=element_blank(),
                   panel.background=element_blank(),
                   panel.border=element_blank(),
                   panel.grid.major=element_blank(),
                   panel.grid.minor=element_blank(),
                   plot.background=element_blank())
    q
1
I've always found that the key to getting consistent canvas and all other dimensions is to control the graphic output device directly. Open one with png(), pdf(), or other favorite and specifically set the dimensions in pixels, cm, or inches to the output that suits your needs. Any further help would need a fully reproducible example with data, which you didn't supply above (hex is missing). - Forrest R. Stevens
sorry about the missing hex...I will add it. I agree with you. What I didn't mention, is that this ggplot is getting used in a Shiny app. So I can't control the graphics output device in an otherwise reasonable manner like you've suggested. PS aside from the hex, everything should be reproducible. - tumultous_rooster
Both shiny::plotOutput and shiny::renderPlot take height and width arguments... - Gregor Thomas
They do...but this will merely squeeze my unnecessarily large canvas into some height and width. The extra white space, courtesy of ggplot, will remain. Now if I were to remove the extra whitespace from my canvas, then your suggestion will solve any other sizing issues that may come up. - tumultous_rooster
Thanks for fixing it. I'm still committed to my comment that you can adjust the height and clear the majority of your white space issue. The rest of the boundary is your standard internal margin that can be set with the plot.margin theme option. Though how this behaves interacting with shiny I don't know. - Forrest R. Stevens

1 Answers

9
votes

Using the ggplot2 plot.margin and/or panel.margin theme options you should be able to control the internal margins, once you've adequately set the output dimensions of the canvas. This certainly will work for normal graphics devices and should also work within the shiny application:

library(ggplot2)
library(grid)

hex=c("#CC0000", "#90BD31", "#178CCB")    

q <- ggplot(data=NULL)
    q <- q + geom_rect(data=NULL, aes(xmin=0, xmax=1, ymin=0.5, ymax=1.5), fill=hex[1])
    q <- q + geom_rect(data=NULL, aes(xmin=1.5, xmax=2.5, ymin=0.5, ymax=1.5), fill=hex[2])
    q <- q + geom_rect(data=NULL, aes(xmin=3, xmax=4, ymin=0.5, ymax=1.5), fill=hex[3])
    q <- q + annotate("text", x=.5, y=0.1, label='Impaired', size=4)
    q <- q + annotate("text", x=2, y=0.1, label='Normal', size=4)
    q <- q + annotate("text", x=3.5, y=0.1, label='Optimal', size=4)
    q <- q + coord_fixed()
    q <- q + theme_classic()
    q <- q + theme(axis.line=element_blank(),
                   axis.text.x=element_blank(),
                   axis.text.y=element_blank(),
                   axis.ticks=element_blank(),
                   axis.title.x=element_blank(),
                   axis.title.y=element_blank(),
                   panel.background=element_blank(),
                   panel.border=element_blank(),
                   panel.grid.major=element_blank(),
                   panel.grid.minor=element_blank(),
                   plot.background=element_blank(),
                   plot.margin=unit(c(0,0,0,0), "cm"),
                   panel.margin=unit(c(0,0,0,0), "cm"))
    q

No margin output