2016/03/02

Incanterのグラフのフォントが文字化けする問題(Clojure)

ClojureのIncanter, 便利なライブラリですが, 日本語などを使った場合, 表示されるフォントが文字化けするという問題があります.

ちなみに, こんな感じ.

元は, 次のようなデータ.
(def top-family-names
  [["佐藤" 313079]
   ["鈴木" 268103]
   ["高橋" 226090]
   ["田中" 205560]
   ["伊藤" 171104]
   ["山本" 167767]
   ["渡辺" 166831]
   ["中村" 163789]
   ["小林" 162481]
   ["加藤" 133341]])
※データは, 同姓同名探しと名前ランキングより.

勿論, 日本語を使わないとか, ローマ字表記にするいう選択肢もありますが, 日本語の処理を行う場合, 各軸の値が日本語の場合は避けて通れません.

上記の場合, 日本の苗字トップ10を表示させたつもりなのですが, 凡例は勿論, 各データの内容もわからなくなってしまいます. 唯一正しく表示されているのは, 数値のみです.

調べると, Google Groupsに解決策がありました.
https://groups.google.com/forum/#!topic/incanter/s_5OR-OP9gw

Fontを変えれば良いようです. というわけでMSゴシックへフォントを変更しました.
(use '(incanter core charts))
(import 'java.awt.Font)

(defn view-incanter [xy-values]
  (let [xs (map first xy-values)
        ys (map second xy-values)
        chart (bar-chart xs ys :vertical false
                         :x-label "family names" :y-label "number of people")
        _ (-> chart .getCategoryPlot .getDomainAxis
              (.setTickLabelFont (new Font "MS ゴシック" Font/BOLD 10)))]
    (save chart "family-names.png")))

(view-incanter top-family-names)
という形です.

これを描写すると,

こんな感じで, 軸ラベルは変更できませんが, 縦軸の値は日本語化できました.
(-> chart .getCategoryPlot .getDomainAxis
    (.setTickLabelFont (new Font "MS ゴシック" Font/BOLD 10)))
の部分で縦軸のフォントを変えることができます. 横軸を変える場合は, .getDomainAxis→.getRangeAxisで変えられると思われます.

しかし, ここまで来ると, 軸ラベルもすべて一括して日本語で表示できるようにしたくなります. そして, 調べていて分かったのですが, Incanterのプロットは, JavaのJFreeChartを使ってプロットしているようです. そして, JFreeChartには, グラフが文字化けした場合のおまじないがありました.

JFreeChart – グラフ中の日本語が文字化けしないようにするには - TK FACTORY

そしてそれは,
ChartFactory.setChartTheme(StandardChartTheme.createLegacyTheme());
だそうです. というわけで,
(import 'org.jfree.chart.ChartFactory)
(import 'org.jfree.chart.StandardChartTheme)
(ChartFactory/setChartTheme (StandardChartTheme/createLegacyTheme))
を描画前に入れると, 文字化けが修正されます(ただし, メソッド名にあるように, テーマも変更されてしまいますが).
これは, 次のようにプロットされます.

見た目を気にしないなら, とりあえず, これでOKですね.