Is there a way to individually change the color of the text of a cell when using tableGrob and ggplot2?
For instance in the code below it'd be great if the cell with 1 could be blue and the cell with 2 could be red, with 3:8 all black.
library(ggplot2)
library(grid)
mytable = as.table(matrix(c("1","2","3","4","5","6","7","8"),ncol=2,byrow=TRUE))
mytable = tableGrob(mytable,gpar.coretext = gpar(col = "black", cex = 1))
mydf = data.frame(x = 1:10,y = 1:10)
ggplot( mydf, aes(x, y)) + annotation_custom(mytable)
Edit
gridExtra >=2.0 was rewritten from scratch, and low-level editing is now possible. I'll leave the old answer below for completeness.
Original answer
grid.table
doesn't allow post-editing of the grob; it should probably be reimplemented using the recent makeContext strategy from the grid package, but that's not very likely to happen.If you really want a table based on grid graphics, you're probably better off writing your own function. Here's a possible start,
With gridExtra >=2.0 aesthetic parameters can be specified via the theme argument, e.g.
Alternatively, the grobs may be edited before drawing.
Much to my disappointment, this does not seem to be easy. The
tableGrob
function callsmakeTableGrobs
to layout the grid object and returns a fully calculatedgTree
structure. It would be nice if you could intercept that, change some properties, and continue on; unfortunately the drawing gets done withgridExtra:::drawDetails.table
and that function insists on callingmakeTableGrobs
again, essentially killing any opportunity for customization.But it's not impossible. Basically we can create our own version of
drawDetails.table
that doesn't do the reprocessing. Here's the function fromgridExtra
with one addedif
statement at the beginning.By defining this function in the global environment, it will take precedence over the one in
gridExtra
. This will allow us to customize the table before it gets drawn and not have our changes get reset. Here's code to change the colors of the values in the first two rows as you requested.And that produces this plot.
So the syntax is a bit cryptic, but let me explain with this line
The
mytable
object is really just a decorated list. It has anlg
item which is what's calculated frommakeTableGrobs
and has all the rawgrid
elements inside. Thelgt
element under that is another list that has all the text layers. For this table,lgt
has 15 elements. One for each square in the table starting with the "empty" one in the upper left. They go in order top-to-bottom, left-to-right, so the cell with 1 is[[7]]
in the list. If you runstr(mytable$lg$lgt[[7]])
you can see the properties that make up that text grob. You will also notice a section forgp
where you can set the color of the text via thecol
element. So we change it from the default "black" to the desired "red".What we are doing isn't part of the official API so it should be considered a hack and as such may be fragile to future changes in the libraries involved (
ggplot2
,grid
,gridExtra
). But hopefully this will at least help you get started in customizing your table.