ggplot geom_point: 如何设置自定义绘图符号的字体?
ggplot geom_point: how to set font of custom plotting symbols?
使用 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)
如果用于符号的字体具有这些特殊字符,则此方法工作正常。否则显然失败了。我知道我们可以明确定义字体并使用 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)
然而,在 geom_point
中,这些字符也来自字体,这一事实让我很好奇覆盖默认值的方法是什么。
我检查了这个试图遵循 this example 的情节,并以这种方式找到了要点:
gr <- ggplotGrob(p)
gr[['grobs']][[6]]$children$geom_point
这里有 x
、y
、size
、lwd
(在上面的示例中使用)等,但没有字体。另外我想知道如何直接自动地从根 grob 中找到点的 grob,例如grid::getGrob
,例如在引用的示例中 grid::grid.edit
找到它们。
我发现了一些有前途的代码 here,它使用了 editGtable
,一种我在任何包中都找不到的方法,也许是一个旧方法。然后我尝试 editGrob
没有成功:
font <- gpar(fontfamily = 'DejaVu Sans', fontsize = 14)
editGrob(gr[['grobs']][[6]], 'geom_point.points', grep = TRUE, global = TRUE, gp = font)
以下是一些 hack,但您可以将点图层包装在新的 class 中,将字体系列分配给点的图形参数。在下面的示例中,新的 class 调用父方法在图层和键中绘制点,然后将字体系列分配给图形参数。
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)
由 reprex package (v2.0.0)
于 2021-08-29 创建
使用不支持 unicode 字符的字体系列:
使用 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)
如果用于符号的字体具有这些特殊字符,则此方法工作正常。否则显然失败了。我知道我们可以明确定义字体并使用 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)
然而,在 geom_point
中,这些字符也来自字体,这一事实让我很好奇覆盖默认值的方法是什么。
我检查了这个试图遵循 this example 的情节,并以这种方式找到了要点:
gr <- ggplotGrob(p)
gr[['grobs']][[6]]$children$geom_point
这里有 x
、y
、size
、lwd
(在上面的示例中使用)等,但没有字体。另外我想知道如何直接自动地从根 grob 中找到点的 grob,例如grid::getGrob
,例如在引用的示例中 grid::grid.edit
找到它们。
我发现了一些有前途的代码 here,它使用了 editGtable
,一种我在任何包中都找不到的方法,也许是一个旧方法。然后我尝试 editGrob
没有成功:
font <- gpar(fontfamily = 'DejaVu Sans', fontsize = 14)
editGrob(gr[['grobs']][[6]], 'geom_point.points', grep = TRUE, global = TRUE, gp = font)
以下是一些 hack,但您可以将点图层包装在新的 class 中,将字体系列分配给点的图形参数。在下面的示例中,新的 class 调用父方法在图层和键中绘制点,然后将字体系列分配给图形参数。
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)
由 reprex package (v2.0.0)
于 2021-08-29 创建使用不支持 unicode 字符的字体系列: