matplotlibで作成したグラフの軸ラベルを斜めにする

optimized scatter with narrow ticks

今回の記事では、グラフの軸ラベルを斜めにする方法を扱います。
いくつか方法はありますが、その中から個人的に納得しやすく、応用にも使いやすいと感じた方法を紹介します。

コードと結果例

細かな説明の前に、描画部分と結果を紹介します。

まず、前提として、下記のコードを実行しています。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
import datetime

準備したデータフレームはこのような感じです。5分ごとのデータを1000行用意しました。

c_df.head()
datetimeC1
02018-03-01 00:00:000.000000
12018-03-01 00:10:001.764052
22018-03-01 00:20:002.164210
32018-03-01 00:30:003.142948
42018-03-01 00:40:005.383841

何も考えないでプロットした場合

まずは何も考えずに描画してみます。

fig, ax = plt.subplots()
ax.plot(c_df["datetime"], c_df["C1"])

label_overwrapped_graph

ご覧の通り、日付が重なってしまっています。

軸ラベルを回転させた場合

今度は、軸ラベルを回転させて描画を行います。

fig, ax = plt.subplots()
ax.plot(c_df["datetime"], c_df["C1"])
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, fontsize=10);

graph with xlabel not overwrapped

軸ラベルを45度回転させて、重ならないように表示することができました。

解説

今回のポイントは

plt.setp(labels, rotation=45, fontsize=10)

の部分です。

丁寧に書くと、matplotlib.pyplot.setp(obj, *args, **kwards)ですね。

setpは”set property”の略です。

この関数はオブジェクトを第一引数に受け取り、そのオブジェクトにpropertyを付与するような役割を果たします。

今回はget.xticklabels()で回収してきたオブジェクトにrotationとfontsizeを付与しているような形です。

なので、例えば描画対象をオブジェクトとして拾っておけば、色や太さを変えることなどもできます。これは後ほど応用例としてご紹介します。

ちなみに、今回引数で与えたlabelsがどのような中身か確認しておくと、

fig, ax = plt.subplots()
ax.plot(c_df["datetime"], c_df["C1"])
labels = ax.get_xticklabels()
print("Entity of labels is {}".format(labels))
#plt.setp(labels, rotation=45, fontsize=10);
    Entity of labels is <a list of 8 Text xticklabel objects>

のように、オブジェクトになっていました。

応用例

setpでグラフの色と透明度を変える

簡単な応用例として、まずは先ほどのグラフの色と透明度を変えてみます。
この例では、plotした際の返り値をlineという変数に格納しています。

fig, ax = plt.subplots()
line = ax.plot(c_df["datetime"], c_df["C1"])
labels = ax.get_xticklabels()
print("Entity of line is {}".format(line))
print("Entity of labels is {}".format(labels))
plt.setp(line, color="k", alpha=0.5)
plt.setp(labels, rotation=45, fontsize=10);

順序が前後しますが、グラフはこちらです。

graph with black line

また、print文の中身はこちらです。

    Entity of line is [<matplotlib.lines.Line2D object at 0x116cc7358>]
    Entity of labels is <a list of 8 Text xticklabel objects>

目的通り、グラフの色と透明度を変えることができています。

散布図への応用

今度は、散布図に応用してみます。
今回は以下のようなデータフレームを準備しています。

c_df.head()
datetimeC1C2C3
02018-03-01 00:00:000.0000001.0000001.000000
12018-03-01 00:10:001.7640522.3315870.688216
22018-03-01 00:20:002.1642103.0468651.417220
32018-03-01 00:30:003.1429481.5014651.635041
42018-03-01 00:40:005.3838411.4930810.735949

単純にプロットした結果がこちら。

fig, ax = plt.subplots(figsize=(5,5))
ax.scatter(c_df["C1"], c_df["C2"])
ax.scatter(c_df["C1"], c_df["C3"])

simple scatter

グラフを見る限り、特に軸ラベルを回転する必要はなさそうです。

しかし、今後の応用を考えて、軸ラベルの回転とプロットの色の変更などを行ってみた結果がこちらです。

fig, ax = plt.subplots(figsize=(5,5))
plot1 =ax.scatter(c_df["C1"], c_df["C2"])
plot2 = ax.scatter(c_df["C1"], c_df["C3"])
xlabels = ax.get_xticklabels()
ylabels = ax.get_yticklabels()
plt.setp(plot1, color="b", alpha=0.5)
plt.setp(plot2, color="k", alpha=0.5)
plt.setp(xlabels, rotation=45, fontsize=10)
plt.setp(ylabels, rotation=45, fontsize=10);
# 以下はタイトルやラベルなどの付与
ax.set_title("Scatter Plot")
ax.set_xlabel("C1")
ax.set_ylabel("Value")
ax.legend(loc="upper right")

optimized scatter

いい感じのグラフになりました。

軸ラベルの刻みを変えたグラフ

ついでに、刻み幅を20ではなく10にしたいと思ったので、作成してみました。

fig, ax = plt.subplots(figsize=(5,5))
plot1 =ax.scatter(c_df["C1"], c_df["C2"])
plot2 = ax.scatter(c_df["C1"], c_df["C3"])
new_xticklabel = np.arange(-100, 101, 10)
ax.set_xticks(new_xticklabel)
ax.set_xticklabels(new_xticklabel)
xlabels = ax.get_xticklabels()
ylabels = ax.get_yticklabels()
ax.set_xlim([-80,  40])

plt.setp(plot1, color="b", alpha=0.5)
plt.setp(plot2, color="k", alpha=0.5)
plt.setp(xlabels, rotation=45, fontsize=10)
plt.setp(ylabels, rotation=45, fontsize=10)

# 以下はタイトルやラベルなどの付与
ax.set_title("Scatter Plot")
ax.set_xlabel("C1")
ax.set_ylabel("Value")
ax.legend(loc="upper right")

optimized scatter with narrow ticks

軸ラベルだけでなく、軸そのものにも変更を加えるところがポイントでしょうか。
ここでは、new_xticklabelという名称で-100から100まで10刻みのnumpy arrayを作成しておき、軸と軸ラベルの両方にその値を使用しています。

まとめ

グラフの軸ラベルを斜めにする方法を紹介しました。

意図的に軸をセットするときは初めからオプションでrotationを入れられることも多いですが、他の方法があると知っておくことも役に立つかと思いますので、機会があれば試していただければと思います。

参考資料

https://matplotlib.org/api/_as_gen/matplotlib.pyplot.setp.html
https://stackoverflow.com/questions/41953648/matplotlib-with-dates-changing-labels-and-ticks-for-monthly-data