知に至る病

お勉強したことを忘れないように書き留めています。

R で日本語入りグラフを WYSIWYG する方法

問題

R でグラフに日本語を使う場合,デバイスごとにフォントデータベースがあるせいで問題が生じることがあります。 たとえば,同じ系統の書体であってもデバイスによって family に指定する値が違ったり,画面にプロットしたものを PDF に保存すると日本語が文字化けしたりします。 文字化けを防ぐためには画面にプロットする段階で family = "Japan1" などと指定する必要があるのですが,画面上ではデフォルトフォントによる描画となってしまいます。

ここでは,画面と PDF でのフォントの指定を統一し,文字化けを防ぎつつ表示もできるだけ一致させる設定を紹介します。 デバイスを意識しながら作業するのは認知的に負荷がかかりますし,フォントの指定を統一できれば出力先を切り替えるのも簡単になります。 また,インタラクティブに作成したグラフをそのまま PDF として保存するためには,画面上の表示と PDF での表示ができるだけ一致していた方が望ましいと考えられます。

方法

各デバイスのフォントデータベースに明朝体とゴシック体のエントリを追加してやります。 エントリは key = value の形式になっており,key が family に指定するフォントファミリーで,value がそのフォントファミリーが指定されたときの描画に使うフォントです。 key に同じものを使用し,value にはデバイスごとに適した日本語フォントを指定します。

設定

.Rprofile でフォントを設定している箇所に以下のような記述を追加します。

setHook(packageEvent("grDevices", "onLoad"), function(...) {

    ...

    ## 画面への描画で使用する日本語フォント
    grDevices::windowsFonts(
        mincho = grDevices::windowsFont("MS Mincho"),
        gothic = grDevices::windowsFont("MS Gothic")
    );

    ## PDF への描画で使用する日本語フォント
    grDevices::pdfFonts(
        mincho = grDevices::pdfFonts()$Japan1,
        gothic = grDevices::pdfFonts()$Japan1GothicBBB
    );
});

画面と PDF それぞれのフォントデータベースに明朝体とゴシック体のエントリを追加しています。 PDF については既存のエントリを単純にコピーしていますが,CIDFont() 関数を使って自分で CID フォントを定義することもできます。

結果

これで family = "mincho" としてプロットすれば,出力先デバイスが画面のときには「MS 明朝」という物理フォントで描画され,PDF のときには「明朝体」という論理フォントの情報が使用されます。 PDF には物理フォントは埋め込まれず,ファイルを開いた際に適当な明朝体の物理フォントで代替して表示されます。

family を指定しなかった場合は,デフォルトのフォントで描画されます。 つまり,画面では Rdevga で指定したフォントが使われ,PDF では .Rprofile で設定したフォントが使われます。

> plot(1:5, type="n")
> text(2, 3, "日本語")
> text(3, 3, "日本語", family="mincho")
> text(4, 3, "日本語", family="gothic")
> dev.copy2pdf(file="plot.pdf")

もちろん,par(family = "mincho") でフォントを指定してから描画したり,pdf(file = "plot.pdf") でデバイスを開いて直接描画したりしても大丈夫です。

考察

この方法の欠点としては,コードの汎用性が低下することが挙げられます。 デバイスを切り替えるのが容易になるという意味で描画コードの再利用性は上がると思いますが,他人と共有しづらくなるという意味で描画コードの汎用性は低下します。