Creating grid graphics with grid.layout

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Creating grid graphics with grid.layout

Jeffrey Horner
Hi,

I recently created a function which uses grid with a viewport
constructed with grid.layout() to position four plots on a plot device.
My question is what's the best way to programatically traverse each
element of the viewport?

The grid is 5x5 and the four plots occupy positions (2,2), (4,2), (2,4),
and (4,4).

Here's the viewport code:

  pushViewport(
         viewport(
             layout=grid.layout(
                 nrow=5,
                 ncol=5,
                 widths=unit(
                     c(margin[2],1,margin[6],1,margin[4]),
                     c('npc','null','npc','null','npc')),
                 heights=unit(
                     c(margin[3],1,margin[5],1,margin[1]),
                     c('npc','null','npc','null','npc'))
             )
         )
     )

margin is a numeric vector of length 6 which resp defines the bottom,
left, top, right, horizontal, and veritical margins (the cross hairs
between the 4 plots). This is to allow the user to define how much
margin should exist around all plots and between the plots.

I then use lapply to visit only those viewports to place the plots by
specifying an x and y vector like so:

x <- c(2,4,2,4)
y <- c(2,2,4,4)
i <- 1
lapply(list(plot1,plot2,plot3,plot4),function(j){
    print(j,vp=viewport(layout.pos.col=x[i],layout.pos.row=y[i])
    i <<- i + 1
})

Looks kludgey. Is there a better way?

Also, I created debug code to visit those viewports where *nothing* is
supposed to be printed except for a grey box with black edges:

z <- outer(logical(5),logical(5),"==")
for (i in 1:length(x)) z[x[i],y[i]] <- FALSE
for (i in 1:5){
    for (j in 1:5){
       if (z[i,j])
          grid.rect(gp=gpar(fill="grey"),
            vp=viewport(layout.pos.col=i,layout.pos.row=j))
    }
}

This looks kludgey as well. Any other ways outer there that are more
elegant?

Thanks,

Jeff

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
Reply | Threaded
Open this post in threaded view
|

Re: Creating grid graphics with grid.layout

Paul Murrell
Hi

If using integer indices is awkward, you could push a viewport tree with
the relevant viewports given useful names.  Then you can downViewport()
using the names (if those plots are lattice plots, then you might even
be able to use the 'draw.in' argument).  Is that the sort of thing you
are looking for?

Paul


Jeff Horner wrote:

> Hi,
>
> I recently created a function which uses grid with a viewport
> constructed with grid.layout() to position four plots on a plot device.
> My question is what's the best way to programatically traverse each
> element of the viewport?
>
> The grid is 5x5 and the four plots occupy positions (2,2), (4,2), (2,4),
> and (4,4).
>
> Here's the viewport code:
>
>   pushViewport(
>          viewport(
>              layout=grid.layout(
>                  nrow=5,
>                  ncol=5,
>                  widths=unit(
>                      c(margin[2],1,margin[6],1,margin[4]),
>                      c('npc','null','npc','null','npc')),
>                  heights=unit(
>                      c(margin[3],1,margin[5],1,margin[1]),
>                      c('npc','null','npc','null','npc'))
>              )
>          )
>      )
>
> margin is a numeric vector of length 6 which resp defines the bottom,
> left, top, right, horizontal, and veritical margins (the cross hairs
> between the 4 plots). This is to allow the user to define how much
> margin should exist around all plots and between the plots.
>
> I then use lapply to visit only those viewports to place the plots by
> specifying an x and y vector like so:
>
> x <- c(2,4,2,4)
> y <- c(2,2,4,4)
> i <- 1
> lapply(list(plot1,plot2,plot3,plot4),function(j){
>     print(j,vp=viewport(layout.pos.col=x[i],layout.pos.row=y[i])
>     i <<- i + 1
> })
>
> Looks kludgey. Is there a better way?
>
> Also, I created debug code to visit those viewports where *nothing* is
> supposed to be printed except for a grey box with black edges:
>
> z <- outer(logical(5),logical(5),"==")
> for (i in 1:length(x)) z[x[i],y[i]] <- FALSE
> for (i in 1:5){
>     for (j in 1:5){
>        if (z[i,j])
>           grid.rect(gp=gpar(fill="grey"),
>             vp=viewport(layout.pos.col=i,layout.pos.row=j))
>     }
> }
>
> This looks kludgey as well. Any other ways outer there that are more
> elegant?
>
> Thanks,
>
> Jeff
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.

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

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
Reply | Threaded
Open this post in threaded view
|

Re: Creating grid graphics with grid.layout

Jeffrey Horner
Paul Murrell wrote:
> Hi
>
> If using integer indices is awkward, you could push a viewport tree with
> the relevant viewports given useful names.  Then you can downViewport()
> using the names (if those plots are lattice plots, then you might even
> be able to use the 'draw.in' argument).  Is that the sort of thing you
> are looking for?

Actually no, integer is just fine, and querying viewports by name would
be slower, no?. I more wanted to confirm that my approach was sound,
using lapply and loops, and that I was using as much of the grid
vectorizing features that were available. For instance, a few iterations
ago I attempted to construct what I thought was a vector of viewports
like so:

x <- c(2,4,2,4)
y <- c(2,2,4,4)
print(...,vp=viewport(layout.pos.col=x,layout.pos.row=y)

which would print ... to each viewport. I realize now that specifying a
vector for layout.pos.* args is just to construct one larger viewport of
the adjacent viewports, right?

Thanks for the quick feedback!

Jeff

> Paul
>
>
> Jeff Horner wrote:
>> Hi,
>>
>> I recently created a function which uses grid with a viewport
>> constructed with grid.layout() to position four plots on a plot
>> device. My question is what's the best way to programatically traverse
>> each element of the viewport?
>>
>> The grid is 5x5 and the four plots occupy positions (2,2), (4,2),
>> (2,4), and (4,4).
>>
>> Here's the viewport code:
>>
>>   pushViewport(
>>          viewport(
>>              layout=grid.layout(
>>                  nrow=5,
>>                  ncol=5,
>>                  widths=unit(
>>                      c(margin[2],1,margin[6],1,margin[4]),
>>                      c('npc','null','npc','null','npc')),
>>                  heights=unit(
>>                      c(margin[3],1,margin[5],1,margin[1]),
>>                      c('npc','null','npc','null','npc'))
>>              )
>>          )
>>      )
>>
>> margin is a numeric vector of length 6 which resp defines the bottom,
>> left, top, right, horizontal, and veritical margins (the cross hairs
>> between the 4 plots). This is to allow the user to define how much
>> margin should exist around all plots and between the plots.
>>
>> I then use lapply to visit only those viewports to place the plots by
>> specifying an x and y vector like so:
>>
>> x <- c(2,4,2,4)
>> y <- c(2,2,4,4)
>> i <- 1
>> lapply(list(plot1,plot2,plot3,plot4),function(j){
>>     print(j,vp=viewport(layout.pos.col=x[i],layout.pos.row=y[i])
>>     i <<- i + 1
>> })
>>
>> Looks kludgey. Is there a better way?
>>
>> Also, I created debug code to visit those viewports where *nothing* is
>> supposed to be printed except for a grey box with black edges:
>>
>> z <- outer(logical(5),logical(5),"==")
>> for (i in 1:length(x)) z[x[i],y[i]] <- FALSE
>> for (i in 1:5){
>>     for (j in 1:5){
>>        if (z[i,j])
>>           grid.rect(gp=gpar(fill="grey"),
>>             vp=viewport(layout.pos.col=i,layout.pos.row=j))
>>     }
>> }
>>
>> This looks kludgey as well. Any other ways outer there that are more
>> elegant?
>>
>> Thanks,
>>
>> Jeff
>>
>> ______________________________________________
>> [hidden email] mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-help
>> PLEASE do read the posting guide
>> http://www.R-project.org/posting-guide.html
>> and provide commented, minimal, self-contained, reproducible code.
>

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.