2017年8月11日金曜日

Python3でmatplotlibの棒グラフをモノクロでも見やすくする

Pythonの作図ライブラリであるmatplotlibを使うとグラフを作成できる(Raspberry PiとPython3でグラフを作成する)。matlotlibはグラフの色分けを自動で行ってくれて、カラーで表示するときは問題ない。しかし、モノクロで印刷したいときなどには判別しにくいときがある。そこでPandasのDataFrameから作成する積み上げ棒グラフで、棒に模様を設定してモノクロでも見やすくしてみる。

OSはRaspbian(Jessie)、その他の環境は以下の通り。


まずは模様なしの積み上げ棒グラフを作成。
import pandas as pd
import datetime as dt
import numpy as np

# matplotlibをターミナルでも使えるようにインポート
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

# 日付データのインデックス作成
dates = pd.date_range(
    start = '4/1/2017',
    periods=15
)

# 0-9の乱数で配列データ作成
values = np.random.randint(10, size=(15, 5))
# データフレーム作成
columns=['a', 'b', 'c', 'd', 'e']
df = pd.DataFrame(values, index=dates, columns=columns)

# Axesオブジェクトの取得
ax = plt.subplot(111)

# 積み上げ棒グラフ作成
df.plot.bar(ax=ax, stacked=True)

# x軸の目盛りラベルを設定
labels = df.index.strftime('%Y-%m-%d')
ax.set_xticklabels(labels, rotation=60)

# 目盛りの文字サイズを小さくする
plt.tick_params(labelsize=6)

# グラフをちょうどいい位置に自動調整
plt.tight_layout()

# グラフをpngで出力
plt.savefig('sample1.png')

Python3で実行するとsample1.pngが作成され、以下のようなグラフになる。

棒グラフに模様を設定するには、棒グラフを作成するbarメソッドのオプションhatchに模様を設定する方法があるが、この方法だと棒グラフ全体が同じ模様になってしまう。
# 棒グラフの模様を'/'に設定
df.plot.bar(ax=ax, stacked=True, hatch='/')
barメソッドのhatchオプションに'/'を設定したときのグラフ。

そこでどうするかというと、patch(積み上げ棒グラフの項目ごとの長方形部分を表すオブジェクト)を取得して、set_hatchメソッドでhatchを設定する。ちなみに、hatchに指定できる模様はmatplotlib.collections.PatchCollection.set_hatchに記載されている。

/   - diagonal hatching
\   - back diagonal
|   - vertical
-   - horizontal
+   - crossed
x   - crossed diagonal
o   - small circle
O   - large circle
.   - dots
*   - stars

実際に積み上げ棒グラフの模様を変えてみる。
import pandas as pd
import datetime as dt
import numpy as np

# matplotlibをターミナルでも使えるようにインポート
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

# 日付データのインデックス作成
dates = pd.date_range(
    start = '4/1/2017',
    periods=15
)
# 0-9の乱数で配列データ作成
values = np.random.randint(10, size=(15, 5))
# データフレーム作成
columns=['a', 'b', 'c', 'd', 'e']
df = pd.DataFrame(values, index=dates, columns=columns)

# Axesオブジェクトの取得
ax = plt.subplot(111)

# 積み上げ棒グラフ作成
df.plot.bar(ax=ax, stacked=True)

# a~e列ごとに棒グラフの模様を変える
patches = ax.patches
hatches = ['/', '.', '*', '\\', 'o']
for i, patch in enumerate(patches):
    patch.set_hatch(hatches[i//len(df.index)])

# x軸の目盛りラベルを設定
labels = df.index.strftime('%Y-%m-%d')
ax.set_xticklabels(labels, rotation=60)

# 目盛りの文字サイズを小さくする
plt.tick_params(labelsize=6)

# グラフをちょうどいい位置に自動調整
plt.tight_layout()

# グラフをpngで出力
plt.savefig('sample3.png')

結果は以下の通り。

0 件のコメント:

コメントを投稿