ggplot geom_point:如何设置自定义绘图符号的字体?

dee*_*nes 5 r heatmap ggplot2 gtable

随着ggplot::geom_point我们能够设置使用绘图符号的任意字符scale_shape_manual.我将举例说明目的:使用三角形在每个单元格中创建一个具有两个值的热图:

require(ggplot2)

data <- data.frame(
    val = rnorm(40),
    grp = c(rep('a', 20), rep('b', 20)),
    x   = rep(letters[1:4], 5),
    y   = rep(letters[1:5], 4)
)

p <- ggplot(data, aes(x = x, y = y, color = val, shape = grp)) +
    geom_point(size = 18) +
    scale_shape_manual(values=c("\u25E4","\u25E2")) +
    theme_minimal() +
    theme(panel.grid = element_blank())

ggsave('triangle-tiles.pdf', device = cairo_pdf, width = 4.1, height = 3.5)
Run Code Online (Sandbox Code Playgroud)

带有geom_point的三角形热图

如果用于符号的字体具有这些特殊字符,则此方法可以正常工作.否则显然是失败的.我知道我们可以明确地定义字体并获得相同的结果geom_text:

require(dplyr)

data <- data %>% mutate(sym = ifelse(grp == 'a', "\u25E4", "\u25E2"))

p <- ggplot(data, aes(x = x, y = y, color = val, label = sym)) +
    geom_text(size = 18, family = 'DejaVu Sans') +
    theme_minimal() +
    theme(
        panel.grid = element_blank()
    )

ggsave('triangle-tiles-2.pdf', device = cairo_pdf, width = 4.1, height = 3.5)
Run Code Online (Sandbox Code Playgroud)

然而,在geom_point这些中来自字体的字符这一事实让我非常好奇是什么是覆盖默认值的方法.

我检查了这个情节的grob试图按照这个例子,并以这种方式找到了点:

gr <- ggplotGrob(p)
gr[['grobs']][[6]]$children$geom_point
Run Code Online (Sandbox Code Playgroud)

在这里,我们x,y,size,lwd(例如,在使用以上)等,但没有任何字样.此外,我想知道如何直接和自动地找到来自根grob的点的grob,例如grid::getGrob,例如在引用的示例中grid::grid.edit找到它们.

我在这里发现了一些有用的代码,这个代码editGtable在任何软件包中都找不到,也许是一个旧代码.然后我尝试editGrob没有成功:

font <- gpar(fontfamily = 'DejaVu Sans', fontsize = 14)
editGrob(gr[['grobs']][[6]], 'geom_point.points', grep = TRUE, global = TRUE, gp = font)
Run Code Online (Sandbox Code Playgroud)

teu*_*and 3

下面是一些 hack,但是您可以将 pointlayer 包装在一个新类中,该类将 fontfamily 分配给点的图形参数。在下面的示例中,新类调用父方法来绘制图层中的点和键,然后将字体系列分配给图形参数。

require(ggplot2)
#> Loading required package: ggplot2

point_with_family <- function(layer, family) {
  old_geom <- layer$geom
  new_geom <- ggproto(
    NULL, old_geom,
    draw_panel = function(self, data, panel_params, coord, na.rm = FALSE) {
      pts <- ggproto_parent(GeomPoint, self)$draw_panel(
        data, panel_params, coord, na.rm = na.rm
      )
      pts$gp$fontfamily <- family
      pts
    },
    draw_key = function(self, data, params, size) {
      pts <- ggproto_parent(GeomPoint, self)$draw_key(
        data, params, size
      )
      pts$gp$fontfamily <- family
      pts
    }
  )
  layer$geom <- new_geom
  layer
}

data <- data.frame(
  val = rnorm(40),
  grp = c(rep('a', 20), rep('b', 20)),
  x   = rep(letters[1:4], 5),
  y   = rep(letters[1:5], 4)
)

p <- ggplot(data, aes(x = x, y = y, color = val, shape = grp)) +
  point_with_family(geom_point(size = 18), "DejaVu Sans") +
  scale_shape_manual(values=c("\u25E4","\u25E2")) +
  theme_minimal() +
  theme(panel.grid = element_blank())

ggsave('triangle-tiles-2.pdf', plot = p, device = cairo_pdf, width = 4.1, height = 3.5)
Run Code Online (Sandbox Code Playgroud)

由reprex 包(v2.0.0)创建于 2021-08-29

在此输入图像描述

使用不支持 unicode 字符的字体系列:

在此输入图像描述