[R] matrix operations on grobs and grid units

baptiste auguie baptiste.auguie at googlemail.com
Sat Sep 19 21:17:29 CEST 2009


A few amendments might make this improved code more readable,

e = expression(alpha,"testing very large width", hat(beta),
integral(f(x)*dx, a, b))

library(grid)

rowMax.units <- function(u, nrow){ # rowMax with a fake matrix of units
 matrix.indices <- matrix(seq_along(u), nrow=nrow)
 do.call(unit.c, lapply(seq(1, nrow), function(ii) {
  max(u[matrix.indices[ii, ]])
 }))
}

colMax.units <- function(u, ncol){ # colMax with a fake matrix of units
 matrix.indices <- matrix(seq_along(u), ncol=ncol)
 do.call(unit.c, lapply(seq(1, ncol), function(ii) {
  max(u[matrix.indices[, ii]])
 }))
}


makeTableGrobs <- function(e, ncol, nrow, equal.width = F, equal.height=F,
just = c("center", "center"),
       gpar.text = gpar(col="black", cex=1),
       gpar.fill = gpar(fill = "grey95", col="white", lwd=1.5)) {

n <- length(e) # number of labels

stopifnot(!n%%2) # only rectangular layouts

if(missing(ncol) & missing(nrow)){
nm <- n2mfrow(n)      # pretty default layout
ncol = nm[1]
nrow = nm[2]
}

makeOneLabel <- function(label.ind){
textGrob(label=e[label.ind], gp=gpar.text,
name=paste("cells-label-",label.ind, sep=""))
}

makeOneCell <- function(label.ind){
rectGrob(gp=gpar.fill, name=paste("cells-fill-",label.ind, sep=""))
}

 lg <- lapply(seq_along(e), makeOneLabel) # list of text grobs
 lf <- lapply(seq_along(e), makeOneCell) # list of rect grobs

 wg <- lapply(lg, grobWidth) # list of grob widths
 hg <- lapply(lg, grobHeight) # list of grob heights

 widths.all <- do.call(unit.c, wg) # all grob widths
 heights.all <- do.call(unit.c, hg)    #all grob heights

 widths <- colMax.units(widths.all, ncol) # all column widths
 heights <- rowMax.units(heights.all, nrow) # all row heights

 if(equal.width)
   widths <- rep(max(widths), length(widths))
 if(equal.height)
   heights <- rep(max(heights), length(heights))

 gcells = frameGrob(name="table.cells", vp = "cells",
   layout = grid.layout(nrow, ncol, just=just,
     widths = widths, heights = heights) )

 label.ind <- 1   # index running accross labels

 for (ii in seq(1, ncol, 1)) {
   for (jj in seq(1, nrow, 1)) {

     gcells = placeGrob(gcells, lf[[label.ind]], row=jj, col=ii)
     gcells = placeGrob(gcells, lg[[label.ind]], row=jj, col=ii)

     label.ind <- label.ind + 1
   }
 }

 gl = gList( gcells)

 gl
}

# tests
vp = viewport(name="cells")
g1 <- gTree(children=makeTableGrobs(e), childrenvp=vp)
g2 <- gTree(children=makeTableGrobs(e, 4, 1), childrenvp=vp)
g3 <- gTree(children=makeTableGrobs(e, 1, 4), childrenvp=vp)
g4 <- gTree(children=makeTableGrobs(e, equal.w=T), childrenvp=vp)
g5 <- gTree(children=makeTableGrobs(e, equal.h=T), childrenvp=vp)
g6 <- gTree(children=makeTableGrobs(e, equal.h=T, equal.w=T), childrenvp=vp)

source("http://gridextra.googlecode.com/svn-history/r21/trunk/R/arrange2.r")
# wrapper around grid.layout and grid.draw
arrange2(g1, g2, g3, g4, g5, g6, main="Testing different fitting arrangements")


This works as expected, however I would like some advice before going
any further,

- because this layout seems quite common, would it make sense to
provide methods for the following objects? (i) a matrix of grobs; (ii)
a matrix of units; (iii) cbind, rbind, rowMax, colMax methods for a
matrix of units.

- is there a better, recommended way to achieve the same thing?
(examples would be great)

Any comments and suggestions are very welcome.

Best regards,

baptiste




More information about the R-help mailing list