关于ggplot2:将ggplot图形保存为PDF,并在r中嵌入字体

Saving ggplot graph to PDF with fonts embedded in r

我一直在遵循我在网上找到的关于将ggplot图形保存为PDF的建议,但我无法完全使其正常工作。我正在使用extrafont包在Calibri中生成带有文本的图表,但是我的图表却没有文本打印。我不知道我在想什么。我在过程中找不到任何错误。希望其他人可以提供帮助。

这是我使用的代码和过程:

1
2
3
library(extrafont)
font_import(pattern="[C/c]alibri")
loadfonts(device="win")

我此时安装了GhostScript。然后运行以下命令来设置GhostScript位置。

1
Sys.setenv(R_GSCMD ="C:\\\\Program Files\\\\gs\\\\gs9.21\\\\bin\\\\gswin64c.exe")

然后,我使用ggplot生成了一个称为"图表"的图表。该图表在RStudio中看起来很完美,但在PDF中却不完美。

1
ggsave("chart.pdf", plot = chart, width = 6, height = 4)

在这里,我得到的警告显示如下内容:

In grid.Call(C_textBounds, as.graphicsAnnot(x$label), ... : font family 'Calibri' not found in PostScript font database

显然,这些警告应该发生吗?然后我跑...

1
embed_fonts("chart.pdf", outfile="chart_embed.pdf")

不幸的是,毕竟,最终的"嵌入"图表看起来与生成的原始图表没有什么不同,原始图表都没有任何文字。

如果有帮助,下面是生成图表的代码:

1
2
3
4
5
6
7
8
9
10
a <- ggplot(data=stats, aes(x=Date))
Chart <- a + geom_point(aes(y=NevadaTotalNonfarmAllEmployees)) +
      xlab("Date") +
      ylab("Nonfarm Jobs") +
      ggtitle("Nevada Total Jobs") +
      theme(axis.title.x = element_text(size=15, family ="Calibri"),
            axis.title.y = element_text(size=15, family ="Calibri"),
            axis.text.x = element_text(size=10, family ="Calibri"),
            axis.text.y = element_text(size=10, family ="Calibri"),
            plot.title = element_text(hjust=0.5, size=20, family ="Calibri"))

我一直在努力寻找解决办法。也许不是代码而是其他东西?无论哪种方式,谢谢您的协助。


这里有两个问题:(1)将字体加载到R中;(2)使用可与自定义嵌入字体正确配合使用的PDF编写库。

首先,就像其他人提到的那样,在Windows上,通常需要运行extrafont::font_import()来向R注册许多系统字体,但是这可能需要一段时间,并且可能会错过TTF和其他类型的字体。解决此问题的一种方法是使用windowsFonts(name_of_font_inside_r = windowsFont("Name of actual font"))将字体动态加载到R中,而无需加载完整的数据库,如下所示:

1
windowsFonts(Calibri = windowsFont("Calibri"))

这使得R中只能访问一种字体。您可以使用windowsFonts()进行检查。每次运行脚本时,您都必须运行此行-字体加载不会在会话之间持续。加载字体后,即可正常使用:

1
2
3
4
5
6
7
8
library(tidyverse)
df <- data_frame(x = 1:10, y = 2:11)

p <- ggplot(df, aes(x = x, y = y)) +
  geom_point() +
  labs(title ="Yay Calibri") +
  theme_light(base_family ="Calibri")
p

Calibrified

其次,R在Windows和macOS上都内置的PDF书写设备不能很好地处理字体嵌入。但是,R现在包括Cairo图形库,它可以很好地嵌入字体。您可以在ggsave()中指定Cairo设备来使用它,这比处理GhostScript要容易得多:

1
2
ggsave(p, filename ="whatever.pdf", device = cairo_pdf,
       width = 4, height = 3, units ="in")

我发现使用pdfFonts(和/或postscriptFonts)显式注册字体更安全。

该文档包含一个示例,但也可以查看我的fonts模块。这样,注册新字体就像编写一样容易

1
fonts$register_font('Calibri')

在内部,这使用Type1Font创建字体规范,确保正确设置名称并调用pdfFonts

它还确保存在完整的字体规格集(使用extrafont::ttf_import完成)。

与使用font_import为所有字体生成字体指标相比,这种方法要快得多,并且可以提供更多控制权。


我认为您错过了初始化步骤font_import()。请注意,执行此命令可能需要更长的时间。

首先,您可以使用命令windowsFonts()查看可用的字体。我的绘图设备中的当前字体为;

1
2
3
4
5
6
7
8
$serif
[1]"TT Times New Roman"

$sans
[1]"TT Arial"

$mono
[1]"TT Courier New"

之后,您可以导入extrafont库和loadfonts(device ="win")。我还建议在R控制台而不是RStudio中执行这些命令。我建议这样做是因为在RStudio中使用font_import()导入字体时,它可能不会显示y/n提示。

下面,我提供了一个最小的可复制示例;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    library(ggplot2)
    library(extrafont)
    font_import()
    # tell where ghostscript is located. This is required for saving the font in pdf
    Sys.setenv(R_GSCMD ="C:\\\\Program Files\\\\gs\\\\gs9.21\\\\bin\\\\gswin64c.exe") # I have installed 64-bit version of GhostScript. This is why I've used gswin64c.exe. If you have installed 32-bit version of GhostScript, use gswin32c.exe. Failure to specify the correct installed GhostScript will yield error message,"GhostScript not found"
    # create a plot object
p <- ggplot(mtcars, aes(x=wt, y=mpg)) +
  geom_point()+
  ggtitle("Fuel Efficiency of 32 Cars")+
  xlab("Weight (x1000 lb)") + ylab("Miles per Gallon") +
  theme_bw()+
  theme(text=element_text(family="ArialMT", size=14))
# show the plot
print(p)

plot

1
2
3
# save the plot as pdf  
ggsave("figures//ggplot_arialmt.pdf", p, width=20, height=20,
   device ="pdf", units ="cm")

注意

它是唯一可与ggsave()一起使用的ArialMT字体。请参阅此SO帖子。使用任何其他字体保存为pdf时,将在字符上方显示图形。这也是ggsave的未解决问题,自2013年以来未得到解答。