ggplot2 PDF输出中的Unicode字符
Posted
技术标签:
【中文标题】ggplot2 PDF输出中的Unicode字符【英文标题】:Unicode Characters in ggplot2 PDF Output 【发布时间】:2012-09-27 21:41:45 【问题描述】:如何在使用 ggplot2 创建的 PDF 图中将 Unicode 字符用于标签、标题和类似内容?
考虑以下示例:
library(ggplot2)
qplot(Sepal.Length, Petal.Length, data=iris, main="Aʙᴄᴅᴇғɢʜɪᴊᴋʟᴍɴᴏᴘǫʀsᴛᴜᴠᴡxʏᴢ")
ggsave("t.pdf")
情节的标题使用 Unicode 字符(小型大写字母),在输出中显示为 ...
。该问题仅出现在 pdf 绘图中;如果我将最后一行替换为ggsave("t.png")
,则输出符合预期。
我做错了什么?我拥有的 R 脚本采用 UTF-8 编码。一些系统信息:
R version 2.14.1 (2011-12-22)
Platform: x86_64-pc-linux-gnu (64-bit)
locale:
[1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
[3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
[5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
[7] LC_PAPER=C LC_NAME=C
[9] LC_ADDRESS=C LC_TELEPHONE=C
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
在寻找这个问题的解决方案时,我发现了一些evidence,R 使用单字节编码进行多字节编码,例如用于 PDF 或 postscript 输出的 UTF-8。我还找到了一些建议,例如,能够获得Euro sign working,但没有通用的解决方案。
【问题讨论】:
cairo_pdf("t.pdf"); ...; dev.off()
为我工作...见***.com/questions/5886018/…
【参考方案1】:
正如 Ben 所建议的,cairo_pdf()
是你的朋友。它还允许您通过 family
参数在 PDF 中嵌入非 postscript 字体(即 TTF/OTF)(如果您碰巧没有包含要使用的字形的任何 postscript 字体,则至关重要)。例如:
library(ggplot2)
cairo_pdf("example.pdf", family="DejaVu Sans")
qplot(Sepal.Length, Petal.Length, data=iris, main="Aʙᴄᴅᴇғɢʜɪᴊᴋʟᴍɴᴏᴘǫʀsᴛᴜᴠᴡxʏᴢ")
dev.off()
...给出如下所示的 PDF:
另见this question;虽然它看起来与标题没有直接关系,但其中有很多关于让字体在 R 中做你想做的事情。
EDIT cmets 中的每个请求,这里是特定于 windows 的代码:
library(ggplot2)
windowsFonts(myCustomWindowsFontName=windowsFont("DejaVu Sans"))
cairo_pdf("example.pdf", family="myCustomWindowsFontName")
qplot(Sepal.Length, Petal.Length, data=iris, main="Aʙᴄᴅᴇғɢʜɪᴊᴋʟᴍɴᴏᴘǫʀsᴛᴜᴠᴡxʏᴢ")
dev.off()
要使用基本图形命令cairo_pdf()
,首先使用windowsFonts()
命令定义字体系列就足够了,如上所示。当然,请确保您使用系统上实际拥有的字体,并且该字体实际上具有您需要的所有字形。
T以下 cmets 中有关 DLL 文件的说明是我必须执行的操作,以使 library(Cairo)
中的 Cairo()
和 CairoPDF()
命令在 Windows 上工作。那么:
library(ggplot2)
library(Cairo)
windowsFonts(myCustomWindowsFontName=windowsFont("DejaVu Sans"))
CairoPDF("example.pdf")
par(family="myCustomWindowsFontName")
qplot(Sepal.Length, Petal.Length, data=iris, main="Aʙᴄᴅᴇғɢʜɪᴊᴋʟᴍɴᴏᴘǫʀsᴛᴜᴠᴡxʏᴢ")
dev.off()
【讨论】:
谢谢,这适用于我在 Linux 上。我还没有在 Windows 上使用它,既没有使用您提供的代码,也没有使用CairoPDF
。
让 Cairo 包在 Windows 上运行是一件棘手的事情。我为它写了一个小教程here。这有帮助吗?
要让 Cairo 库在 Windows 上运行,请转到 this page,单击 Windows(32/64 位),并在“必需的第三方依赖项”下下载 zlib、cairo、 libpng、fontconfig、freetype 和 expat。解压并收集所有DLL并放入:C:\Program Files\R\R-2.14.0\bin\i386(或在64位系统上C:\Program Files\R\R-2.14.0\bin\x64) .还将 fonts.conf 文件从 fontconfig zip 文件移动到 C:\Program Files\R\R-2.14.0\etc\i386\fonts\。在 64 位系统上,将路径名中的“i386”替换为“x64”;无论您的 R 版本是什么,也可以低于 2.14.0。
感谢您的帮助,但它仍然不适合我。我遵循了您的所有步骤,但是当我执行上面示例中的代码时,标题仍然是垃圾。轴标签正常工作(使用不同字体时也是如此),只是使用 Unicode 字符的标题被弄乱了。输出是“空设备”,不确定是否符合预期。
添加了特定于 Windows 的代码,取自 this question 已在原始答案中提到。如果 that 不起作用,那么您的 R 版本可能是在不支持基于 cairo 的图形的情况下编译的。【参考方案2】:
截至 2020 年和 R 版本 4.0.3,cairo_pdf()
不再是您在 Mac OS X 上的朋友,至少就西里尔文而言 - 请参阅失败图库如下。
TL;DR
如果您必须有西里尔文,只需返回良好的 ole png
驱动程序。 (和你的抗锯齿图告别。)
R -e 'png(filename = "ftw.png"); library(ggplot2); qplot(Sepal.Length, Petal.Length, data=iris, main="Aʙᴄᴅᴇғɢʜɪᴊᴋʟᴍɴᴏᴘǫʀsᴛᴜᴠᴡxʏᴢ"); dev.off()'
open ftw.png
或者,如果您将Rmarkdown 与 knitr 一起使用:
R -e 'rmarkdown::render("foo.Rmd", "pdf_document", output_file="foo.pdf", runtime = "static", output_options = list(dev = "png"))'
失败画廊
开罗的“现代”方法在 v4.0.3 中失败,如下所示。请注意,这不是(或不仅仅是)字体嵌入或渲染问题,因为从生成的 PDF 中选择和粘贴文本也会产生乱码输出。
准备步骤:
-
install the latest R(4.0.3 或更高版本,所有
capabilities()
都显示TRUE
)
R -e 'install.packages(c("Cairo", "ggplot2"), repos="https://cloud.r-project.org")'
原版配置
R -e 'library(ggplot2); qplot(Sepal.Length, Petal.Length, data=iris, main="Aʙᴄᴅᴇғɢʜɪᴊᴋʟᴍɴᴏᴘǫʀsᴛᴜᴠᴡxʏᴢ"); ggsave("fail1.pdf")'
open fail1.pdf
单独使用cairo_pdf()
R -e 'cairo_pdf("fail2.pdf"); library(ggplot2); qplot(Sepal.Length, Petal.Length, data=iris, main="Aʙᴄᴅᴇғɢʜɪᴊᴋʟᴍɴᴏᴘǫʀsᴛᴜᴠᴡxʏᴢ"); dev.off()'
open fail2.pdf
将cairo_pdf()
与自定义(假定符合Unicode)字体一起使用
R -e 'cairo_pdf("fail3.pdf", family = "Arial Unicode MS"); library(ggplot2); qplot(Sepal.Length, Petal.Length, data=iris, main="Aʙᴄᴅᴇғɢʜɪᴊᴋʟᴍɴᴏᴘǫʀsᴛᴜᴠᴡxʏᴢ"); dev.off()'
open fail3.pdf
Comic Sans 的另一次尝试:
R -e 'cairo_pdf("fail3bis.pdf", family = "Comic Sans MS"); library(ggplot2); qplot(Sepal.Length, Petal.Length, data=iris, main="Aʙᴄᴅᴇғɢʜɪᴊᴋʟᴍɴᴏᴘǫʀsᴛᴜᴠᴡxʏᴢ"); dev.off()'
open fail3bis.pdf
还有一些...
使用较旧的“黑暗和暴风雨之夜”版本(3.6.2):
/Library/Frameworks/R.framework/Versions/3.6/Resources/bin/R -e 'cairo_pdf("fail4.pdf", family = "Arial Unicode MS"); library(ggplot2); qplot(Sepal.Length, Petal.Length, data=iris, main="Aʙᴄᴅᴇғɢʜɪᴊᴋʟᴍɴᴏᴘǫʀsᴛᴜᴠᴡxʏᴢ"); dev.off()'
open fail4.pdf
按照@drammock 的建议使用DejaVu Sans
:
R -e 'cairo_pdf("fail5.pdf", family = "DejaVu Sans"); library(ggplot2); qplot(Sepal.Length, Petal.Length, data=iris, main="Aʙᴄᴅᴇғɢʜɪᴊᴋʟᴍɴᴏᴘǫʀsᴛᴜᴠᴡxʏᴢ"); dev.off()'
open fail5.pdf
旧 R 上的 DejaVu Sans:
/Library/Frameworks/R.framework/Versions/3.6/Resources/bin/R -e 'cairo_pdf("fail5bis.pdf", family = "DejaVu Sans"); library(ggplot2); qplot(Sepal.Length, Petal.Length, data=iris, main="Aʙᴄᴅᴇғɢʜɪᴊᴋʟᴍɴᴏᴘǫʀsᴛᴜᴠᴡxʏᴢ"); dev.off()'
open fail5bis.pdf
【讨论】:
字体“符合 unicode”并不意味着它在每个代码点都包含字形。如果您使用我的答案(DejaVu Sans)中显示的字体,它会失败吗?我的答案中的许多小型大写字形都在 unicode 的“语音扩展”块中,Comic Sans 或 Arial MS 中很可能不存在。 @drammock DejaVu Sans 确实是最接近工作的一种(就成功渲染字形的数量而言,与 Arial Unicode MS 并列)。更新了失败图库。 奇怪的是,即使使用 DejaVu Sans 也无法正常工作。 DejaVu Sans 字形表 (dejavu.sourceforge.net/samples/DejaVuSans.pdf) 的第 22 页表明它确实至少有 ᴄ,ᴅ,ᴇ 字形,这些字形并没有出现在您面前(我没有检查每个字形)。值得注意的是,所有失败的代码点都是U+1xxx
,而所有成功的代码点都是U+0xxx
,所以我怀疑是编码问题而不是字体问题。
我很高兴我不是唯一一个遇到这个问题的人。让我感觉不那么孤单了【参考方案3】:
如果您使用ggsave(...)
,您可以致电ggsave(..., device=cairo_pdf)
。
您需要先安装并加载 Cairo 绑定。
install.packages("Cairo")
library(Cairo)
这是full example(不是我的作品)。
【讨论】:
Cairo
包和grDevices::cairo_pdf
有什么关系?以上是关于ggplot2 PDF输出中的Unicode字符的主要内容,如果未能解决你的问题,请参考以下文章