使用 TableGrob 更改单元格的文本颜色 [英] Change text color for cells using TableGrob

查看:27
本文介绍了使用 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆