ggsave在交互模式下可以使用systemfonts包中的字体,但在RScript下不支持

编程语言 2026-07-10

我想把系统中的自定义字体(使用 systemfonts 库)应用到用 ggplot2 绘制的图上,并且希望在不触及R 控制台的情况下编辑程序。然而,ggsave 会在非交互式运行时导致程序失败。将程序稍作修改,改用 pngagg_png(输出相同)来替代 ggsave,似乎解决了问题,但我想知道为什么 ggsave 无法与 systemfonts 在RScript中配合使用,以及是否有什么办法可以解决。

下面是一个示例程序:

library(tidyverse)
library(ragg)
library(systemfonts)

options(warn = 1)

mydata = tribble(
    ~type, ~quantity,
    "Widgets", 1024,
    "Gizmos", 826,
    "Doodads", 1701
)

mydata |> ggplot() +
    geom_bar(
        stat = "identity",
        aes(x = type, y = quantity)
    ) +
    labs(title = "Quantity of widgets, gizmos, and doodads") +
    theme(plot.title = element_text(size = 15, family = "Basteleur"))

ggsave("graph.png", width = 10, height = 7, units = "in")

如果我把整个程序复制并粘贴到一个新的R 会话中,它按预期运行,并生成一个 graph.png 文件,其外观如下: 带有 Basteleur 字体标题的部件、装置和花哨玩意的图形

如果我尝试用 RScript 运行这个程序,甚至 R --no-save < program.r,我得到如下警告和错误。

Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)) :
  font family 'Basteleur' not found in PostScript font database
Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)) :
  font family 'Basteleur' not found in PostScript font database
Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)) :
  font family 'Basteleur' not found in PostScript font database
Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)) :
  font family 'Basteleur' not found in PostScript font database
Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)) :
  font family 'Basteleur' not found in PostScript font database
Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)) :
  font family 'Basteleur' not found in PostScript font database
Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)) :
  font family 'Basteleur' not found in PostScript font database
Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)) :
  font family 'Basteleur' not found in PostScript font database
Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)) :
  font family 'Basteleur' not found in PostScript font database
Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)) :
  font family 'Basteleur' not found in PostScript font database
Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)) :
  font family 'Basteleur' not found in PostScript font database
Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)) :
  font family 'Basteleur' not found in PostScript font database
Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)) :
  font family 'Basteleur' not found in PostScript font database
Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)) :
  font family 'Basteleur' not found in PostScript font database
Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y,  :
  font family 'Basteleur' not found in PostScript font database
Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y,  :
  font family 'Basteleur' not found in PostScript font database
Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y,  :
  font family 'Basteleur' not found in PostScript font database
Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y,  :
  font family 'Basteleur' not found in PostScript font database
Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y,  :
  font family 'Basteleur' not found in PostScript font database
Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y,  :
  font family 'Basteleur' not found in PostScript font database
Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y,  :
  font family 'Basteleur' not found in PostScript font database
Error in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y,  : 
  invalid font type
Calls: <Anonymous> ... drawDetails -> drawDetails.text -> grid.Call.graphics
Execution halted

有没有办法在RScript中使用 systemfonts?你是不是一定要使用 extrafonts

解决方案

执行在 ggsave() 之前就被停止。

没有赋值,

mydata |> ggplot() ...

会触发打印/提前渲染,批处理模式下的默认图形设备恰好是 pdf,而它又不支持 systemfonts。 要验证,请尝试在不设置字体的情况下使其在RStudio外部工作/使用 RScript,你应该会得到两个输出文件:Rplots.pdf 来自 ggplot() 的调用,以及 graph.png 来自 ggsave()

切换到目标设备本应可行,但在批处理模式中我宁愿将 ggplot 对象存储起来并将其传递给 ggsave()

p <- mydata |> ggplot() +
    geom_bar(
        stat = "identity",
        aes(x = type, y = quantity)
    ) +
    labs(title = "Quantity of widgets, gizmos, and doodads") +
    theme(plot.title = element_text(size = 15, family = "Basteleur"))

ggsave("graph.png", p, width = 10, height = 7, units = "in")
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章