使用TableGrob更改单元格的文本颜色
使用tableGrob和ggplot2时,是否可以单独更改单元格文本的颜色?
Is there a way to individually change the color of the text of a cell when using tableGrob and ggplot2?
例如,在下面的代码中,如果具有1的单元格可以是蓝色,而具有2的单元格可以是红色(3:8都是黑色),那将是很好的.
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)
令我非常失望的是,这似乎并不容易. tableGrob
函数调用makeTableGrobs
来布局网格对象并返回完全计算的gTree
结构.如果您可以拦截,更改某些属性并继续,那将是很好的.不幸的是,绘制是使用gridExtra:::drawDetails.table
完成的,并且该函数坚持要再次调用makeTableGrobs
,从根本上消除了进行任何自定义的机会.
Much to my disappointment, this does not seem to be easy. The tableGrob
function calls makeTableGrobs
to layout the grid object and returns a fully calculated gTree
structure. It would be nice if you could intercept that, change some properties, and continue on; unfortunately the drawing gets done with gridExtra:::drawDetails.table
and that function insists on calling makeTableGrobs
again, essentially killing any opportunity for customization.
但这不是不可能的.基本上,我们可以创建自己的drawDetails.table
版本,该版本不进行重新处理.这是gridExtra
中的函数,在开头添加了一个if
语句.
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 from gridExtra
with one added if
statement at the beginning.
drawDetails.table <- function (x, recording = TRUE)
{
lg <- if(!is.null(x$lg)) {
x$lg
} else {
with(x, gridExtra:::makeTableGrobs(as.character(as.matrix(d)),
rows, cols, NROW(d), NCOL(d), parse, row.just = row.just,
col.just = col.just, core.just = core.just, equal.width = equal.width,
equal.height = equal.height, gpar.coretext = gpar.coretext,
gpar.coltext = gpar.coltext, gpar.rowtext = gpar.rowtext,
h.odd.alpha = h.odd.alpha, h.even.alpha = h.even.alpha,
v.odd.alpha = v.odd.alpha, v.even.alpha = v.even.alpha,
gpar.corefill = gpar.corefill, gpar.rowfill = gpar.rowfill,
gpar.colfill = gpar.colfill))
}
widthsv <- convertUnit(lg$widths + x$padding.h, "mm", valueOnly = TRUE)
heightsv <- convertUnit(lg$heights + x$padding.v, "mm", valueOnly = TRUE)
widthsv[1] <- widthsv[1] * as.numeric(x$show.rownames)
widths <- unit(widthsv, "mm")
heightsv[1] <- heightsv[1] * as.numeric(x$show.colnames)
heights <- unit(heightsv, "mm")
cells = viewport(name = "table.cells", layout = grid.layout(lg$nrow +
1, lg$ncol + 1, widths = widths, heights = heights))
pushViewport(cells)
tg <- gridExtra:::arrangeTableGrobs(lg$lgt, lg$lgf, lg$nrow, lg$ncol,
lg$widths, lg$heights, show.colnames = x$show.colnames,
show.rownames = x$show.rownames, padding.h = x$padding.h,
padding.v = x$padding.v, separator = x$separator, show.box = x$show.box,
show.vlines = x$show.vlines, show.hlines = x$show.hlines,
show.namesep = x$show.namesep, show.csep = x$show.csep,
show.rsep = x$show.rsep)
upViewport()
}
通过在全局环境中定义此功能,它将优先于gridExtra
中的功能.这将使我们能够在绘制表格之前自定义表格,而不必重置更改.这是根据您的要求更改前两行中值的颜色的代码.
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.
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))
mytable$lg$lgt[[7]]$gp$col <- "red"
mytable$lg$lgt[[12]]$gp$col <- "blue"
mydf = data.frame(x = 1:10,y = 1:10)
ggplot( mydf, aes(x, y)) + annotation_custom(mytable)
然后就产生了这个情节.
And that produces this plot.
所以语法有点含糊,但让我用这一行来解释
So the syntax is a bit cryptic, but let me explain with this line
mytable$lg$lgt[[7]]$gp$col <- "red"
mytable
对象实际上只是一个修饰列表.它具有一个lg
项,该项是根据makeTableGrobs
计算得出的,并且其中包含所有原始的grid
元素.在其下的lgt
元素是具有所有文本层的另一个列表.对于此表,lgt
具有15个元素.表格中的每个方块一个,以左上角的空"开头.它们按从上到下,从左到右的顺序排列,因此列表中具有1的单元格为[[7]]
.如果运行str(mytable$lg$lgt[[7]])
,则可以看到组成该文本grob的属性.您还会注意到gp
的一部分,您可以在其中通过col
元素设置文本的颜色.因此,我们将其从默认的黑色"更改为所需的红色".
The mytable
object is really just a decorated list. It has an lg
item which is what's calculated from makeTableGrobs
and has all the raw grid
elements inside. The lgt
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 run str(mytable$lg$lgt[[7]])
you can see the properties that make up that text grob. You will also notice a section for gp
where you can set the color of the text via the col
element. So we change it from the default "black" to the desired "red".
我们正在做的事情不是官方API的一部分,因此应将其视为黑客行为,因此对于所涉及的库(ggplot2
,grid
,gridExtra
)中的将来更改可能是脆弱的.但是希望这至少可以帮助您开始自定义表格.
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.