須通り
Sudo Masaaki official site
For the reinstatement of
population ecology.

ぼくとママンとディスカッション

     

ホーム | 統計 Top | Rにおける作図時のフォント設定を極める

Rのコンソールで使用するフォントは、Windowsであればメニューの「編集」「GUIプリファレンス...」から、MacOSでは環境設定の「エディタ」から設定できる。じゃあグラフを描く(描画デバイスを使用する)とき、そこで使うフォントを自由に指定したかったらどうする?今回はRのグラフィック関連パラメータから、フォントに関する項目を抜き出して説明する。極めれば君もナウなヤングにバカウケだ。

なお古典的なフォント管理方法に加え、extrafont による近代的なワークフローについても 2020 年に加筆した。幾分 ggplot2 などの知識を要するが、par よりも体系的な操作が可能で環境依存性も低いので、積極的な移行をおすすめする。

目次

  1. par(font): 太字・イタリック等の書体を指定する
  2. par(family): 作図に用いるフォントファミリーを指定する
  3. フォントファミリーって何なのさ

    par(family="○○") として直接フォント名を指定できるか?

    MacOS X のQuartz Deviceでフォントファミリーを指定する

    Windows のデバイスでフォントファミリーを指定する

    独自に定義されたフォントファミリーを含むグラフをWindowsでPDF保存する際の問題

  4. par(ps): フォントサイズを指定する
  5. (2020.07.25追加)modern Rにおける統一的なフォント指定を行う extrafont パッケージ
  6. (2020.07.25追加)Windows 環境で embed_font() を用いて既存 PDF ファイルへフォントを埋め込む

par(font): 太字・イタリック等の書体を指定する

Rのグラフィックパラメータに par(font) という項目がある。一見すると、このオプションでフォント名が自由に指定できるように思えるのだが、実際にはフォントの書体を選ぶためのパラメータである。

  • font=1 通常の立体
  • font=2 ボールド体
  • font=3 イタリック体(Italic)もしくは斜体(oblique)
  • font=4 ボールド体かつイタリック体
  • (場合によって)font=5 シンボルフォント
plot(1:10 ~ c(1:10), font=3 ) ##plot関数内のオプションとしてフォントをイタリックにした例

par(family): 作図に用いるフォントファミリーを指定する

par(font)が書体を指定するのであれば、フォントそのものは如何に指定するのか?こんなとき、Rで用いられるのが「フォントファミリー」だ。

フォントファミリーって何なのさ

フォントファミリーとは聞き慣れない概念であるが、ここでは「あるフォントにおける、立体や斜体、ボールド体などの書体をまとめた1セット」と解釈しておけば良いだろう。例えて云うならば、 "Helvetica" や "Times New Roman" などが「佐藤」や「鈴木」に類するファミリーの名前であり、その中にある "Bold" や "Italic" などの書体が「太郎」や「花子」や「侘び輔」といった家族の個人名に相当する。

このフォントファミリーを管理するのが、グラフィックパラメータ par の一種である、par(family) である。まずヘルプページにおけるpar(family)の説明、および須藤による日本語訳を下に掲載する。

family

    The name of a font family for drawing text. The maximum allowed length is 200 bytes. This name gets mapped by each graphics device to a device-specific font description. The default value is "" which means that the default device fonts will be used (and what those are should be listed on the help page for the device). Standard values are "serif", "sans" and "mono", and the Hershey font families are also available. (Different devices may define others, and some devices will ignore this setting completely.) This can be specified inline for text.

(日本語訳)テキスト描画に用いるフォントファミリーの名称。最大長は200バイト。この名称は各描画デバイスによって解釈され、描画デバイス特有のフォント指定が為される。デフォルト値は""で、このときデバイスのデフォルトフォントが使用される(そのフォントが何であるかはデバイスのヘルプページに一覧表示される)。標準の値は "serif"、"sans"および"mono"であり、他にHersheyフォントファミリーも使用可能である。(デバイスによってはそれ以外のフォントファミリーも指定可能であるし、また別のデバイスでは指定が完全に無視されることもある。)それぞれのテキストについてインラインで指定することもできる*。

*訳注:familyを引数の1つに取りうる別の作画関数、例えばplot内でfamily="○○"と書いてもよい、ということ。

って何がなんだか分からないゾ。そう、Rにおけるフォントファミリーの指定方法は描画デバイス依存であるため、非常に説明しにくいのだ。しかし利用者レベルで気になるのは、テキトーな作図関数内で (family="なんか適当なフォント名") というワンフレーズを挿むことにより、フォントを指定して描画できるのか?という点であろう。

par(family="○○") として直接フォント名を指定できるか?

結論から言うと描画デバイス(端的には使用しているOS)の種類に依存する。たとえば以下の操作は、MacOS Xでは有効だが、Windowsではエラーを吐く。

par(family="Zapfino") ##テキトーなフォント名を指定してみる
plot(1:10 ~ c(1:10) )
par(family="Hiragino Mincho Pro W6") ##日本語フォントでもok
plot(1:10 ~ c(1:10), xlab="これは日本語")
font zapfino

Fig. 1 | フォントファミリーに直接フォント名として"Zapfino"を指定した例。Macでのみ有効となる。

であれば、プラットフォームを問わずに有効な family="" の指定内容とは何か?それは「予め定義しておいたフォントファミリーの名称」である。

MacOS X のQuartz Deviceでフォントファミリーを指定する

最新の林檎でRを使っている人の場合、特段意識しなければplot()等の作画関数で開かれるグラフ窓は、Quartzという描画エンジンを用いて作成されるはずだ(残念ながら筆者はMacOS 9以前の世界を知らないため、クラシックOSでの使い方は質問されても答えられない)。ここで使われるフォントのセット(フォントファミリー)を定義する関数が、quartzFontである。

  • とりあえずヘルプを参照したいときは、 help(quartzFont) として探す。
  • quartzFonts() と打てば、現在のフォントファミリーとその構成内容の一覧を出力できる。
> quartzFonts()
$serif
[1] "Times New Roman"      "Times-Bold"      "Times-Italic"      "Times-BoldItalic"

$sans
[1] "Helvetica"      "Helvetica-Bold"      "Helvetica-Oblique"      "Helvetica-BoldOblique"

$mono
[1] "Courier"      "Courier-Bold"      "Courier-Oblique"      "Courier-BoldOblique"

初期状態では、上に示した"serif", "sans", "mono"という3つのフォントファミリーが定義されている。各ファミリーにはfont=1から4までに対応するフォント名が、文字列として格納されている。

## 以下のように打てば、グラフの文字をタイプライター風(モノスペースフォント)にできる
> plot(1:10 ~ c(1:10), family="mono")
  • 新しいフォントファミリーを定義することで、好みのフォントをグラフ中に使用できる。
  • 4つの書体に対応するフォントを、長さ4の文字型ベクトル形式で与える必要がある。
#####たとえば新たなフォントファミリーとして、Optimaを使いたい場合

>  quartzFonts( OPTIMA = c("Optima-Regular", "Optima-Bold", "Optima-Italic", "Optima-BoldItalic") ) ## OPTIMAは新造するファミリーの名

> plot(1:10 ~ c(1:10), font=2, pch="f", family="OPTIMA", xlab="Label by Optima Bold")
font_optima

Fig. 2 | quartzFonts() を用いてフォントファミリーにOptima、書体に(2)Boldを定義した例。

さて問題となるのは、ここで指定するフォントの内部名称をどうやって知るかである。幸いなことにMacOS Xには "Font Book.app" が存在する。このアプリケーションを開いて、お望みのフォントの説明を表示させよう。一番上に出てくる「PostScript 名」の項目が、フォントファミリー定義に必要な名称である。

fontbook

Fig. 3 | Font Book.appにおけるフォントの説明例。

Windows のデバイスでフォントファミリーを指定する

こちらはwindowsFonts()という関数を使う。

  • とりあえずヘルプを参照したいときは、 help(windowsFonts) として探す。
  • windowsFonts() と打てば、現在のフォントファミリー名とその構成内容の一覧を出力できる。
> windowsFonts()
$serif
[1] "TT Times New Roman"

$sans
[1] "TT Arial"

$mono
[1] "TT Courier New"

##MacOS XのquartzFontsとの違いとして、こちらはboldとかitalicとかの指定を直接行わない。なおTTはTrueTypeの略。

  • 新しいフォントファミリーを定義することで、好みのフォントをグラフ中に使用できる。
#####たとえば新たなフォントファミリーとして、メイリオを使いたい場合
>  windowsFonts(MEI = windowsFont("Meiryo")) ## "MEI"は新造するファミリーの名
> plot(1:10 ~ c(1:10), font=4, pch="f", family="MEI", xlab="これは日本語")
font zapfino

Fig. 4 | windowsFonts() を用いてフォントファミリーにメイリオを定義した例。

独自に定義されたフォントファミリーを含むグラフをWindowsでPDF保存する際の問題

Windows版のRで、上に示したグラフをPDF保存しようとすると、次のようなエラーが出て保存に失敗する(ラスター画像形式を選んだときは問題ない)。

エラー:  不正なフォントタイプです
 追加情報:   警告メッセージ:
1: font family 'MEI' not found in PostScript font database

理由は単純で、windowsFonts() 内部で新たに定義したファミリーは、別の描画デバイスが司るところのPDF書き出しには、自動的に適用されないのである。

本エラーを回避する一つの方法は、RのPDF作成に用いられるモジュールに対しても windowsFonts のそれと同名、同内容のフォントファミリーを定義することだ。これにより、PDF作成モジュールがそのフォントファミリー指定を解釈できるようになる。この用途には postscriptFonts() という関数を使う。

もう一つは、 R内蔵のPDF出力機能を使用しないことである。この場合、メニューから「印刷...」として、 Adobe Distiller や Ghostscript などの仮想プリンタ機能を呼び出してやれば、PDFファイルへの変換が可能だ(変換ソフトは自分で用意する必要あり)。個人的にはこちらの解決策をお薦めする。

というのも、たとえ最終的にPDFを出力できたとしても、RはデフォルトではPDFにフォントを埋め込まないからである(埋め込みのためには別途 embedFonts などの手続きを経由する必要がある)。たとえば普段Rを使用しているのと異なるマシン環境へ、フォントの埋め込まれていないPDFファイルを移した場合、利用先で文字が表示されないという事故も起こり得る。もし相手が論文の査読者であったりすれば、あなたが心血を注いだ研究が陽の目を見ることは無いであろう。

par(ps): フォントサイズを指定する

ps = "数字" により、描画デバイス内で用いるフォントのサイズをポイント(1/72 inch)単位で指定できる。これは別段、難しい点はない。


### 現在のフォントサイズ設定を確認する
> par("ps")
[1] 12

### フォントサイズを24ポイントに設定。
> par(ps=24)
> plot(1:10 ~ c(1:10))

(2020.07.25追加)modern Rにおける統一的なフォント指定を行う extrafont パッケージ

ここまでの内容は2013年春に執筆したものである。当時は ggplot2 も日本ではあまり普及していなかった。その後 tidyverse の台頭や論文のトレーサビリティーの重視に伴い、作図フローの自動化が広範に図られるようになった。データフレーム(tibble)をパイプラインで加工し、結果を ggplot2 で作図オブジェクトに転化し、必要なら cowplot や patchwork(そのうち解説します)で複数のパネルを連結する。出来上がった作図オブジェクトを ggsave で pdf や eps, emf 等のベクトルグラフィックスに保存する。これらを一貫したコマンド操作で行い、論文の supplementary で再現可能な手順として残しておく。

個人的な変化としては、就職に伴い複数の分離されたマシン環境(Windows 7, Windows 10, MacOS X, Ubuntu Linux)で、それぞれデータ解析/作図/論文執筆を進める必要が生じた。こうなると適当な図を出してから Adobe Illustrator で加工するという方法が使いづらいし、マシンによってフォント指定方法もインストール済みのフォントファミリもバラバラになってしまう。

こうした状況で、R 環境上のフォント指定を統一的に扱うのが extrafont package である。細けえことは CRAN の read me を見てもらうとして、とりあえず導入方法は以下。


# インストール
install.packages("extrafont")

# 最初に入れたとき、新しいフォントをマシンにインストールしたときは、まず利用可能な TrueType font の一覧を構築&登録する。数分かかる。
library(extrafont)
font_import()
loadfonts() # font_import() で作ったフォント一覧を出力デバイスに登録する。

# 上記の操作が終わったら、利用可能なフォントファミリー名を一覧表示してみよう
extrafont::fonts()

> extrafont::fonts()
  [1] "@JustEditMark"                   "Agency FB"                       "Algerian"
  [4] "Arial Black"                     "Arial"                           "Arial Narrow"
  [7] "Arial Rounded MT Bold"           "Bahnschrift"                     "Baskerville Old Face"
 [10] "Bauhaus 93"                      "Bell MT"                         "Berlin Sans FB"
以下省略

# たとえば明朝体を検索したいとき、"Min" で部分一致させてみる
grep(fonts(), pattern="Min", value=TRUE)

> grep(fonts(), pattern="Min", value=TRUE)
[1] "Yu Mincho Demibold" "Yu Mincho Light"    "Yu Mincho"

# 2回目以降の R 立ち上げ時には extrafont のロードのみでおk
library(extrafont)

上記の通り fonts() で、現在 R 環境から extrafont package を通じて呼び出し可能なフォントの一覧を知ることができる。一方、もう少し詳細な情報(マシン内のフォントファイルの名称、インストール場所、利用可能書体、etc.)を表示できるのが fonttable() 関数である。


# フォントテーブル全体を tibble で表示する
library(tidyverse)
tibble(extrafont::fonttable())

> tibble(extrafont::fonttable())
# A tibble: 325 x 10
   package afmfile   fontfile       FullName   FamilyName FontName  Bold  Italic Symbol afmsymfile
                                           
 1 NA      JSEDIT_V~ "C:\\Windows\~ @JustEdit~ @JustEdit~ -JustEdi~ FALSE FALSE  FALSE  NA
 2 NA      AGENCYB.~ "C:\\Windows\~ Agency FB~ Agency FB  AgencyFB~ TRUE  FALSE  FALSE  NA
 3 NA      AGENCYR.~ "C:\\Windows\~ Agency FB  Agency FB  AgencyFB~ FALSE FALSE  FALSE  NA
 4 NA      ALGER.af~ "C:\\Windows\~ Algerian   Algerian   Algerian  FALSE FALSE  FALSE  NA
 5 NA      ariblk.a~ "C:\\Windows\~ Arial Bla~ Arial Bla~ Arial-Bl~ FALSE FALSE  FALSE  NA
 6 NA      arialbi.~ "C:\\Windows\~ Arial Bol~ Arial      Arial-Bo~ TRUE  TRUE   FALSE  NA
 7 NA      arialbd.~ "C:\\Windows\~ Arial Bold Arial      Arial-Bo~ TRUE  FALSE  FALSE  NA
 8 NA      ariali.a~ "C:\\Windows\~ Arial Ita~ Arial      Arial-It~ FALSE TRUE   FALSE  NA
 9 NA      arial.af~ "C:\\Windows\~ Arial      Arial      ArialMT   FALSE FALSE  FALSE  NA
10 NA      ARIALN.a~ "C:\\Windows\~ Arial Nar~ Arial Nar~ ArialNar~ FALSE FALSE  FALSE  NA
# ... with 315 more rows

# なお、上記の操作で windowsFonts にフォントリストが追加登録されている。以下で見れる。
unlist(windowsFonts())

現在この記事を執筆している Windows 10 環境だと、fonts() で認識されるフォントファミリー数は 193 だったが、上記の fonttable() によると 325 種類のフォントファイルが存在する。これはたとえば Arial, Arial Bold, Arial Italic, Arial Bold Italic みたいに、書体が複数合わさってファミリーを構成しているためである。

extrafont を作図に使う

では、実際の作図に extrafont を使っていこう。定番の mtcars 組み込みデータセットをたたき台とする。


data(mtcars)
mtcars

> mtcars
                     mpg cyl  disp  hp drat    wt  qsec vs am gear carb
Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive      21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
Valiant             18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
(以下省略)

公式には base R の plot 関数と、ggplot2 での使用例がいずれも端的に紹介されているが、今回はぜひとも、extrafont と ggplot2 の合わせ技での威力を実感してもらいたい。


# 必要に応じてインストール
install.packages("ggplot2")
install.packages("ggthemes")
install.packages("Cairo")

PDF保存時のフォントの埋め込みに Cairo デバイスを使う。Cairo パッケージを必要に応じてインストールする(ggsave から呼ぶ場合、毎回 R 立ち上げ時に library(Cairo) する必要はない)。当方の環境ではだいぶ前に構築済みで、詳細な手順を失念したので、もし他に依存パッケージや事前準備が必要で動かなかったらごめんなさいである。


library(ggplot2)
library(ggthemes)
library(extrafont)

p <- ggplot(mtcars)
p <- p +
    geom_point(aes(x=hp, y=mpg)) +
    theme_classic(base_size=10) +
    facet_wrap(~cyl) +
    theme(  text=element_text(family="Arial"),
            plot.title=element_text(family="Yu Mincho", face="bold", size=12, hjust=0),
            # 日本語の字形が無いフォントだと title が豆腐になるゾ
            axis.text.x=element_text(family="Stencil", size=14, angle=0, hjust=0.5) ) +
    labs( title="自動車の馬力と燃費の関係", x="hp", y="mpg" )

# デフォルトの作図デバイスに図を表示したいとき
p

# pdf への保存
ggsave("mtcars.hp_mpg.pdf", device=cairo_pdf, plot=p, dpi=300,
        width=11.4/2.54, height=8/2.54)
# png への保存
ggsave("mtcars.hp_mpg.png", type="cairo-png", antialias="subpixel", plot=p, dpi=300,
        width=11.4/2.54, height=8/2.54)

スペースの都合で詳細は省くが、element_text(family="フォントファミリー名") で、図中のパーツごとに細かくフォントを変更できる。

extrafont-ggsave-cairo-png

Fig. 5 | extrafont を用いたフォント指定を ggplot2 の作図フロー内部で行い、ggsave 関数を用いて cairo デバイス経由で png ファイルに保存したグラフ。

なお PDF で出力したファイルへのリンクはこちらにある。

上記のコードでは p と打った時点で、R の別窓が開いてグラフが表示されるはずだ。この窓のメニューからPDFで保存することも可能だが、フォントが埋め込まれていないため、別のマシンに持っていくと表示が崩れることがままある。

Windows 環境の場合、一番簡単な解決策は先ほどインストールした cairo_pdf をデバイスに用いることだ。コードの最下部にあるように、ggsave() という ggplot オブジェクトの直接保存用の関数内において、device=cairo_pdf とするとよい。MacOS X でも同様の方法で大体いけるが、一部の日本語フォントファミリーでは(extrafont::fonts() で認識され p で表示されるのに)なぜか埋め込みが上手くいかなかった。

extrafont を通常の plot で使う

extrafont が入っているR環境では、plot と組み合わせて、 family = "fonts()で表示されるファミリー名" としてフォントを指定しつつ表示することも可能。ただしフォントが埋め込まれた pdf ファイルを保存するには、標準の pdf() デバイスではなく cairo_pdf() デバイスで初期化する必要がある。


# pdf() device の 替わりに cairo_pdf() device を使うよろし
# https://stackoverflow.com/questions/48908273/extrafonts-package-problems-saving-plot-as-pdf-with-missing-text

cairo_pdf("mtcars.hp_mpg_plot.pdf", family="Yu Mincho", width=4, height=4)
plot(x=mtcars$hp, y=mtcars$mpg, main="自動車の馬力と燃費の関係")
dev.off()

# 以下でも動く。この場合 plot 単独で実行しても R Graphics Device にフォントが反映される。
cairo_pdf("mtcars.hp_mpg_plot.pdf", width=4, height=4)
plot(x=mtcars$hp, y=mtcars$mpg, family="Yu Mincho", main="自動車の馬力と燃費の関係")
dev.off()


https://stat.ethz.ch/R-manual/R-patched/library/grDevices/html/cairo.html

svg(filename = if(onefile) "Rplots.svg" else "Rplot%03d.svg",
    width = 7, height = 7, pointsize = 12,
    onefile = FALSE, family = "sans", bg = "white",
    antialias = c("default", "none", "gray", "subpixel"),
    symbolfamily)

cairo_pdf(filename = if(onefile) "Rplots.pdf" else "Rplot%03d.pdf",
          width = 7, height = 7, pointsize = 12,
          onefile = FALSE, family = "sans", bg = "white",
          antialias = c("default", "none", "gray", "subpixel"),
          fallback_resolution = 300, symbolfamily)

cairo_ps(filename = if(onefile) "Rplots.ps" else "Rplot%03d.ps",
         width = 7, height = 7, pointsize = 12,
         onefile = FALSE, family = "sans", bg = "white",
         antialias = c("default", "none", "gray", "subpixel"),
         fallback_resolution = 300, symbolfamily)

extrafont 公式りどみだと pdf() でも動くはずなのだけど、なぜか各レターの文字幅が認識されず、パーツごとに全文字が同じ場所へ重なってしまう。だから base R でフォント弄るのは鬼門だと何度言ったら(愚痴)


cairo_pdf() ではなく普通の pdf() を使うと、以下のように叱られてフォントが反映されない

 50 件以上の警告がありました (最初の 50 個の警告を見るには warnings() を使って下さい)

> warnings()
 警告メッセージ:
1: In axis(side = side, at = at, labels = labels, ...) :
   文字 0x6d に対する文字幅がわかりません
2: In axis(side = side, at = at, labels = labels, ...) :
   文字 0x35 に対する文字幅がわかりません
3: In axis(side = side, at = at, labels = labels, ...) :
   文字 0x30 に対する文字幅がわかりません
4: In axis(side = side, at = at, labels = labels, ...) :
   文字 0x35 に対する文字幅がわかりません

ラスター画像で保存するには?R 標準で用意されている png() device を使うのが一番簡単。type="cairo" というオプションが存在し、アンチエイリアスを掛けることができる。


png("mtcars.hp_mpg_png_plot.png", width=600, height=600, res=150, type="cairo", antialias="subpixel")
plot(x=mtcars$hp, y=mtcars$mpg, family="Yu Mincho", main="自動車の馬力と燃費の関係")
dev.off()

bmp(filename = "Rplot%03d.bmp",
    width = 480, height = 480, units = "px", pointsize = 12,
    bg = "white", res = NA, …,
    type = c("cairo", "Xlib", "quartz"), antialias)

jpeg(filename = "Rplot%03d.jpeg",
     width = 480, height = 480, units = "px", pointsize = 12,
     quality = 75,
     bg = "white", res = NA, …,
     type = c("cairo", "Xlib", "quartz"), antialias)

png(filename = "Rplot%03d.png",
    width = 480, height = 480, units = "px", pointsize = 12,
     bg = "white",  res = NA, …,
    type = c("cairo", "cairo-png", "Xlib", "quartz"), antialias)

tiff(filename = "Rplot%03d.tiff",
     width = 480, height = 480, units = "px", pointsize = 12,
     compression = c("none", "rle", "lzw", "jpeg", "zip", "lzw+p", "zip+p"),
     bg = "white", res = NA,  …,
     type = c("cairo", "Xlib", "quartz"), antialias)

(2020.07.25追加)Windows 環境で embed_font() を用いて既存 PDF ファイルへフォントを埋め込む

そういえば本記事の中で以前「RはデフォルトではPDFにフォントを埋め込まないからである(埋め込みのためには別途 embedFonts などの手続きを経由する必要がある)」と書いたのだけど、plot で作図して GUI メニューから PDF で保存したファイルに、あらためてフォントを埋め込む方法を解説するのをすっかり忘れて7年たった。

ちなみに "embedFonts()" は grDevices という R パッケージに入っている関数なのだけど、我々が先ほど入れた extrafont パッケージにも embed_font() という関数が用意されていて、同様の処理ができる。すなわち、既にローカル環境へ出力された(フォントの埋め込まれていない)PDF に、後からフォントを埋め込める。以下、基本的に Windows マシン上での挙動となる。

まず Ghostscript というソフトウェアをインストールする。まあ PDF の形式変換を行うプログラムだと乱暴に理解してほしい。然る後、R の環境変数に Ghostscript の本体プログラムである gswin32c.exe または gswin64c.exe (自分がインストールしたほう)の居場所を耳打ちしてやる。

directory of ghostscript binary

Fig. 6 | Windows のエクスプローラから見た Ghostscript のインストール先。上記だと C:\gs\gs9.22\bin になる。


# R コンソールから R の環境変数を閲覧するコマンド
Sys.getenv()

# R の環境変数に新たな値をセットするコマンド
Sys.setenv(R_GSCMD = "C:/gs/gs9.22/bin/gswin64c.exe")

上でセットした R_GSCMD を参照して、extrafont パッケージの embed_fonts() 関数が内部的に Ghostscript プログラムを呼び出し、PDF ファイルの書き換えを行う。embed_fonts() の第一引数に既存のファイル名を、第二引数の outfile に書き換え後のファイル名を指定する。


# 先ほどローカルに出力した既存の PDF ファイルにフォントを埋め込む
embed_fonts("mtcars.hp_mpg_plot.pdf", outfile="mtcars.hp_mpg_plot.embed.pdf")

(2020.07.27追加)R で OpenType フォントを使う

上記の extrafont では原則として TrueType フォントしか使えない。これはちょっとした問題で、たとえば最近の Windows 環境だと BIZ UDゴシックもメイリオもMSゴシックも Times New Roman も Calibri も、基本的には OpenType 形式でインストールされる。本記事の上の方に書いてあるように windowsFonts() であれば R Graphics Device への plot 時に、ユーザー定義済みのフォントファミリーを表示されることができて、これにはメイリオ等の OpenType フォントも原則的には含まれる。

だが実験してみたところ、そのまま cairo_pdf() しても OpenType の字形が埋め込まれない(文字幅は反映されているので豆腐になる)。ちなみに一旦ローカルへpdfを吐いてから embed_fonts() しても直らない。

想定される解決法は、cairo_pdf() にも同名のファミリーを定義してやることである。しかしよく分からない結果に


# windowsFont() でファミリーを定義してやる
windowsFonts(MEI = windowsFont("Meiryo")) ## "MEI"は新造するファミリーの名
unlist(windowsFonts())

# エラーは出ないがローカルに吐いたPDFのタイトルが豆腐になる
cairo_pdf("mtcars.hp_mpg_opentype_plot.pdf", width=4, height=4)
plot(x=mtcars$hp, y=mtcars$mpg, family="MEI", main="自動車の馬力と燃費の関係")
dev.off()

# 一旦吐き出したファイルに embed しても無駄っぽい
embed_fonts("mtcars.hp_mpg_opentype_plot.pdf", outfile="mtcars.hp_mpg_opentype_plot.embed.pdf")

# 以下もエラーは出ないが豆腐になる
cairo_pdf("mtcars.hp_mpg_opentype_plot.pdf", family="MEI", width=4, height=4)
plot(x=mtcars$hp, y=mtcars$mpg, main="自動車の馬力と燃費の関係")
dev.off()

# なぜか以下は正しく埋め込まれる
cairo_pdf("mtcars.hp_mpg_opentype_plot.pdf", family="Meiryo", width=4, height=4)
plot(x=mtcars$hp, y=mtcars$mpg, main="自動車の馬力と燃費の関係")
dev.off()

# なぜか以下も正しく埋め込まれる
windowsFonts(MSMincho = windowsFont("MS Mincho"))
cairo_pdf("mtcars.hp_mpg_UD_plot.pdf", family="MS Mincho", width=4, height=4)
plot(x=mtcars$hp, y=mtcars$mpg, main="自動車の馬力と燃費の関係")
dev.off()

# なぜか以下も正しく埋め込まれる(css スタイル名 → https://labs.keninatateka.com/uddkyo/ で指定してやるのがコツ)
windowsFonts(UDDigiKyokashoN = windowsFont("UD Digi Kyokasho N-R"))
cairo_pdf("mtcars.hp_mpg_UD_plot.pdf", family="UD Digi Kyokasho N-R", width=4, height=4)
plot(x=mtcars$hp, y=mtcars$mpg, main="自動車の馬力と燃費の関係")
dev.off()


# 以下はいずれもエラーになる
windowsFonts(MSMincho = windowsFont("MS Mincho"))
plot(x=mtcars$hp, y=mtcars$mpg, family="MSMincho", main="自動車の馬力と燃費の関係")
plot(x=mtcars$hp, y=mtcars$mpg, family="MS Mincho", main="自動車の馬力と燃費の関係")

何が起こった?なぜ cairo_pdf() で MEI は無効なのに Meiryo は有効?

な、なんか狐につつまれたような
気がする・・・。
            ∧_∧
            /    ヽ
            | `  ´|
      <>○<>\= o/
      // ヽ\⊂ ̄ , ヽ
      / ∧_∧ヽ  ̄   ヽ
     /,( ;´∀`)ヽ ,ゝ  |___, ヘ
     | ヽ\`yノ )(   |   <   |
     ヽ ___ノ_と_ノ\_<_ノ

どうも OTC (OpenType Collection) の関係らしい。