[R] matrix operations on grobs and grid units
baptiste auguie
baptiste.auguie at googlemail.com
Sat Sep 19 17:17:43 CEST 2009
Dear list,
As a minimal test of a more complex grid layout, I'm trying to find a
clean and efficient way to arrange text grobs in a rectangular layout.
The labels may be expressions, or text with a fontsize different of
the default, which means that the cell sizes should probably be
calculated using grobWidth() and grobHeight() as opposed to simpler
stringWidth() and stringHeight(). (Correct?).
The input of this function is a vector of labels, which are arranged
into a matrix layout. Below is my current version, followed by a few
questions.
e = expression(alpha,"testing very large width", hat(beta),
integral(f(x)*dx, a, b))
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,
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=""))
}
lg <- lapply(seq_along(e), makeOneLabel) # list of grobs
wg <- lapply(lg, grobWidth) # list of grob widths
hg <- lapply(lg, grobHeight) # list of grob heights
widths.all <- do.call(unit.c, wg)
heights.all <- do.call(unit.c, hg)
widths <- colMax.units(widths.all, ncol)
heights <- rowMax.units(heights.all, nrow)
gcells = frameGrob(name="table.cells", vp = "cells",
layout = grid.layout(nrow, ncol, just=just,
widths = widths,
heights = heights) )
label.ind <- 1 # index running for the vector of labels
for (ii in seq(1, ncol, 1)) {
for (jj in seq(1, nrow, 1)) {
gcells = placeGrob(gcells, rectGrob(gp=gpar.fill,
name=paste("cells-fill-r",ii, "-c",jj,sep="")),
row=jj, col=ii)
text.grob.ij = textGrob(label=e[label.ind],
gp=gpar.text, name=paste("cells-label-r",ii,
"-c",jj,sep=""))
gcells = placeGrob(gcells, text.grob.ij, row=jj, col=ii)
label.ind <- label.ind + 1
}
}
gList( gcells)
}
# tests
vp = viewport(name="cells")
grid.draw(gTree(children=makeTableGrobs(e), childrenvp=vp))
grid.newpage()
grid.draw(gTree(children=makeTableGrobs(e, 1, 4), childrenvp=vp))
grid.newpage()
grid.draw(gTree(children=makeTableGrobs(e, 4, 1), childrenvp=vp))
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 other comments are very welcome.
Best regards,
baptiste
More information about the R-help
mailing list