[R] grid layout scaling viewport width based solely on height

Paul Murrell p.murrell at auckland.ac.nz
Sun Aug 10 22:41:49 CEST 2008


Hi


Peter Cowan wrote:
> Paul,
> 
> On Wed, Aug 6, 2008 at 1:40 PM, Paul Murrell <p.murrell at auckland.ac.nz> wrote:
>>> I'm trying to write a function that produces a main plotting region
>>> with several square plots along the right side.  Ideally the size of
>>> right side plots will scale only with the height of the entire plot,
>>> yet never overlap with another secondary plot.  The following two
>>> snippets get close, however, as I resize the plot horizontally the
>>> right side plots (green squares) get smaller whereas I'd like them to
>>> remain the same size.  It seems the answer lies in setting the layout
>>> width for the side plot column in a clever way that I haven't been
>>> able to discover.  Any suggestions on how to achieve that effect or
>>> other improvements to the below code are most welcome.
>>>
>>> Hopefully, my explanation makes my goal clear.  Also note, the real
>>> application is a function that will have arbitrary numbers of side
>>> plots.
> 
>> Sorry, I'm not completely sure what you want to end up with, but do
>> either of the following come close ?
> 
> Thanks for the response.  Of the two suggestions the latter is close
> to what I was hoping four.  However, ideally there would be no gap
> between the side plots when the plot is 'tall'.  Phrased another way,
> as the total plot gets larger, I would like the second column of the
> lay1 to take up a greater proportion of the figure. So that a resize
> in the Y, changes the allocation of column space in the X.  I don't
> suppose that is possible, is it?


It is, with a little more work ...

# Side plots square and take up as much room as they are allowed
# A special grob that is not drawn, but has the required height for the
# side plots
squareGrob <- grob(height=unit(.1, "npc"),
                   cl="squareGrob")
# A method for determining the width of the special grob based
# on its height.
# The important point is that this calculation will get redone
# every time the squareGrob is asked for its width.
widthDetails.squareGrob <- function(x) {
      convertUnit(unit(.1, "npc"),
                  "npc",
                  "y", "dimension",
                  "x", "dimension")
}
# A layout where the width of the second column is based
# on the width of the special grob (first column width
# takes up whatever width is left over)
lay1 <- grid.layout(10, 2,
                    widths=unit.c(unit(1, "null"),
                                  grobWidth(squareGrob)),
                    heights=unit(.1, "npc"))

... Once that squareGrob is defined, you can use it anywhere, so that's
a one-off cost.  The following code shows the resulting layout ...

# grid.newpage()
pushViewport(viewport(layout=lay1))

pushViewport(viewport(layout.pos.col=1))
grid.rect(gp=gpar(fill="grey"))
popViewport()

for (i in 1:10) {
    pushViewport(viewport(layout.pos.col=2,
                          layout.pos.row=i))
    grid.rect(gp=gpar(fill="light grey"))
    popViewport()
}

... does that do the job ?

Paul


> Cheers
> 
> Peter
> 
>> # Side plots square and attached to each other
>> # With "tall" plot, get gaps top and bottom
>> # With "wide" plot, get gap on the right
>> lay1 <- grid.layout(1, 2, widths=c(10, 1))
>> lay2 <- grid.layout(10, 1, respect=TRUE, just="left")
>>
>> # grid.newpage()
>> pushViewport(viewport(width=.8, height=.8, layout=lay1))
>> grid.rect(gp=gpar(col="grey"))
>>
>> pushViewport(viewport(layout.pos.col=1))
>> grid.rect(gp=gpar(fill="grey"))
>> popViewport()
>>
>> pushViewport(viewport(layout.pos.col=2,
>>                      layout=lay2))
>> for (i in 1:10) {
>>    pushViewport(viewport(layout.pos.row=i))
>>    grid.rect(gp=gpar(fill="light grey"))
>>    popViewport()
>> }
>> popViewport()
>>
>>
>> # Side plots square and separate from each other
>> # With "tall" plot, get gaps between vertically
>> # With "wide" plot, get gap on the right
>> lay1 <- grid.layout(10, 2, widths=c(10, 1))
>>
>> # grid.newpage()
>> pushViewport(viewport(width=.8, height=.8, layout=lay1))
>> grid.rect(gp=gpar(col="grey"))
>>
>> pushViewport(viewport(layout.pos.col=1))
>> grid.rect(gp=gpar(fill="grey"))
>> popViewport()
>>
>> for (i in 1:10) {
>>    pushViewport(viewport(layout.pos.col=2,
>>                          layout.pos.row=i))
>>    pushViewport(viewport(x=0, width=unit(1, "snpc"),
>>                          height=unit(1, "snpc"), just="left"))
>>    grid.rect(gp=gpar(fill="light grey"))
>>    popViewport(2)
>> }
>>
>> Paul
>>

-- 
Dr Paul Murrell
Department of Statistics
The University of Auckland
Private Bag 92019
Auckland
New Zealand
64 9 3737599 x85392
paul at stat.auckland.ac.nz
http://www.stat.auckland.ac.nz/~paul/



More information about the R-help mailing list