使用 TableGrob 更改单元格的文本颜色 [英] Change text color for cells using 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)
这就产生了这个情节.
所以语法有点神秘,但让我用这一行来解释
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.
这篇关于使用 TableGrob 更改单元格的文本颜色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!