LoginSignup
4
2

More than 1 year has passed since last update.

subplotsで全グラフのxticksのrotationを変更したい

Last updated at Posted at 2022-01-23

Pythonのmatplotlibのsubplotsで複数のグラフを1枚に描画していたのですが
軸のラベルが日時とかで長くなってしまったので回転したくなりました。

なので全てのグラフの軸ラベルを回転させたいと思って、
plt.xticks(rotation=60)
を指定したらうまくいかなかった、という話の解決案です。

 
さて、まずは適当にデータを作りましてこれを2行×3列のsubplotsを描画します。

▼データ作成

import pandas as pd
import matplotlib.pyplot as plt

### パラメータ
nrows_num=2
ncols_num=3

### データ
x_label=['ああああああああああああああああああああ',
         'いいいいいいいいいいいいいいいいいいいい',
         'うううううううううううううううううううう']
y_var1=[11, 12, 11]
y_var2=[21, 22, 21]
y_var3=[31, 32, 31]
y_var4=[41, 42, 41]
y_var5=[51, 52, 51]
y_var6=[61, 62, 61]

plt_df=pd.DataFrame({'x_label':x_label,
                     'y_var1':y_var1,
                     'y_var2':y_var2,
                     'y_var3':y_var3,
                     'y_var4':y_var4,
                     'y_var5':y_var5,
                     'y_var6':y_var6})

 
▼グラフ描画

# 日本語を表示
plt.rcParams['font.family'] = "MS Gothic"

# グラフを描画
fig, axes=plt.subplots(nrows=nrows_num, ncols=ncols_num, figsize=(18, 12))
plt_df[['x_label', 'y_var1']].plot(x='x_label', ax=axes[0, 0])
plt_df[['x_label', 'y_var2']].plot(x='x_label', ax=axes[0, 1])
plt_df[['x_label', 'y_var3']].plot(x='x_label', ax=axes[0, 2])
plt_df[['x_label', 'y_var4']].plot(x='x_label', ax=axes[1, 0])
plt_df[['x_label', 'y_var5']].plot(x='x_label', ax=axes[1, 1])
plt_df[['x_label', 'y_var6']].plot(x='x_label', ax=axes[1, 2])

# グラフを表示
plt.show()

 
▼結果
gazou1.png

ラベルは適当に長くしてますが重なって読めないので
plt.xticks(rotation=60)
で回転させてみたら。。。

▼グラフ描画(全グラフのxticksを回転させたい)

# 日本語を表示
plt.rcParams['font.family'] = "MS Gothic"

# グラフを描画
fig, axes=plt.subplots(nrows=nrows_num, ncols=ncols_num, figsize=(18, 12))
plt_df[['x_label', 'y_var1']].plot(x='x_label', ax=axes[0, 0])
plt_df[['x_label', 'y_var2']].plot(x='x_label', ax=axes[0, 1])
plt_df[['x_label', 'y_var3']].plot(x='x_label', ax=axes[0, 2])
plt_df[['x_label', 'y_var4']].plot(x='x_label', ax=axes[1, 0])
plt_df[['x_label', 'y_var5']].plot(x='x_label', ax=axes[1, 1])
plt_df[['x_label', 'y_var6']].plot(x='x_label', ax=axes[1, 2])

# x軸の項目名を斜めにしたい
plt.xticks(rotation=60)

# グラフを表示
plt.show()

 
▼結果
gazou2_kakou.png

と何故か右下しか回転しなかったという罠。
(多分pltの最後だけがrotationしたのではないかと)

でネットで検索したのですが思いの外簡単な解決法がなく
ようやく見つけたヒントをもとに解決できたのでまとめました。

 
▼グラフ描画(全グラフのxticksを回転させた)

# 日本語を表示
plt.rcParams['font.family'] = "MS Gothic"

# グラフを描画
fig, axes=plt.subplots(nrows=nrows_num, ncols=ncols_num, figsize=(18, 12))
plt_df[['x_label', 'y_var1']].plot(x='x_label', ax=axes[0, 0])
plt_df[['x_label', 'y_var2']].plot(x='x_label', ax=axes[0, 1])
plt_df[['x_label', 'y_var3']].plot(x='x_label', ax=axes[0, 2])
plt_df[['x_label', 'y_var4']].plot(x='x_label', ax=axes[1, 0])
plt_df[['x_label', 'y_var5']].plot(x='x_label', ax=axes[1, 1])
plt_df[['x_label', 'y_var6']].plot(x='x_label', ax=axes[1, 2])

# x軸の項目名を斜めにしたい
for tick in axes[0, 0].get_xticklabels():
    tick.set_rotation(60)

for tick in axes[0, 1].get_xticklabels():
    tick.set_rotation(60)

for tick in axes[0, 2].get_xticklabels():
    tick.set_rotation(60)

for tick in axes[1, 0].get_xticklabels():
    tick.set_rotation(60)

for tick in axes[1, 1].get_xticklabels():
    tick.set_rotation(60)

for tick in axes[1, 2].get_xticklabels():
    tick.set_rotation(60)

# グラフを表示
plt.show()

 
▼結果
gazou3.png

内容はプログラムと結果のとおりですが
今回はget_xticklabelsで一度tickを取得してそれぞれをset_rotationで回転させましたと。
⇒すなわち全ての軸ラベル1つ1つに対して回転させたという方針です。

全てのグラフの設定を冗長的に書きたくないなら
for文でループさせても良いでしょうし、
逆に6つのグラフのうち特定のグラフだけ回転させたい、ということもできますね。

 
▼グラフ描画(全グラフのxticksを回転させた/for文で回してみた)

# 日本語を表示
plt.rcParams['font.family'] = "MS Gothic"

# グラフを描画
fig, axes=plt.subplots(nrows=nrows_num, ncols=ncols_num, figsize=(18, 12))
plt_df[['x_label', 'y_var1']].plot(x='x_label', ax=axes[0, 0])
plt_df[['x_label', 'y_var2']].plot(x='x_label', ax=axes[0, 1])
plt_df[['x_label', 'y_var3']].plot(x='x_label', ax=axes[0, 2])
plt_df[['x_label', 'y_var4']].plot(x='x_label', ax=axes[1, 0])
plt_df[['x_label', 'y_var5']].plot(x='x_label', ax=axes[1, 1])
plt_df[['x_label', 'y_var6']].plot(x='x_label', ax=axes[1, 2])

# x軸の項目名を斜めにしたい
for i in range(0, nrows_num):
    for j in range(0, ncols_num):
        for tick in axes[i, j].get_xticklabels():
            tick.set_rotation(60)

# グラフを表示
plt.show()

(結果は省略)

 
内容的には以上です。
(上の段の軸ラベルが下のグラフに重なってるじゃないか、というツッコミは今回は無しの方向で)

もっと簡単に解決できるかなー、と思っていたら思いの外文献もなく苦戦しましたので
どなたかのご参考になればと思い記事にしました。

for文を使用しない、もっと簡単な設定でできそうな気もしているのですが、
備忘録も含め記事として残しておきます。

======================================================
(追記)
コメントでご指摘を頂き、
自分のPCで試してみましたので修正版を記載させていただきます。

▼修正版

# 日本語を表示
plt.rcParams['font.family'] = "MS Gothic"

# グラフを描画
fig, axes=plt.subplots(nrows=nrows_num, ncols=ncols_num, figsize=(18, 12))
plt_df[['x_label', 'y_var1']].plot(x='x_label', ax=axes[0, 0])
plt_df[['x_label', 'y_var2']].plot(x='x_label', ax=axes[0, 1])
plt_df[['x_label', 'y_var3']].plot(x='x_label', ax=axes[0, 2])
plt_df[['x_label', 'y_var4']].plot(x='x_label', ax=axes[1, 0])
plt_df[['x_label', 'y_var5']].plot(x='x_label', ax=axes[1, 1])
plt_df[['x_label', 'y_var6']].plot(x='x_label', ax=axes[1, 2])

# x軸の項目名を斜めにしたい
for ax in axes.flatten():
    ax.set_xticklabels(ax.get_xticklabels(), rotation=60)

# グラフを表示
plt.show()

こちらでうまくいきました。
ご指摘いただきありがとうございました。

また別のPCで実行したらうまくいかなかったので
事象等をメモとして以下記載しておきます。

 
・Warningが出た&ラベルが消えた
別端末でax.set_xticklabels()を実行した際、
UserWarning: FixedFormatter should only be used together with FixedLocator
というWarningが出て、かつラベルが消えてしまいました。
(画像はないですが、前述のグラフの"あああ~"とかが消えてしまいました)

 
で、色々調べた結果

import matplotlib.ticker as ticker

# 日本語を表示
plt.rcParams['font.family'] = "MS Gothic"

# グラフを描画
fig, axes=plt.subplots(nrows=nrows_num, ncols=ncols_num, figsize=(18, 12))
plt_df[['x_label', 'y_var1']].plot(x='x_label', ax=axes[0, 0])
plt_df[['x_label', 'y_var2']].plot(x='x_label', ax=axes[0, 1])
plt_df[['x_label', 'y_var3']].plot(x='x_label', ax=axes[0, 2])
plt_df[['x_label', 'y_var4']].plot(x='x_label', ax=axes[1, 0])
plt_df[['x_label', 'y_var5']].plot(x='x_label', ax=axes[1, 1])
plt_df[['x_label', 'y_var6']].plot(x='x_label', ax=axes[1, 2])

# x軸の項目名を斜めにしたい
for ax in axes.flatten():
    ax.xaxis.set_major_locator(ticker.FixedLocator(ax.get_xticks().tolist()))
    ax.set_xticklabels(ax.get_xticklabels(), rotation=60)

# グラフを表示
plt.show()

という行を追加してWarningは解消したのですが、
x軸のラベルの表示が消えたまま…。

 
・更に調べて修正
更に調べた結果、下記で解消(目標は達成)されました。

# 日本語を表示
plt.rcParams['font.family'] = "MS Gothic"

# グラフを描画
fig, axes=plt.subplots(nrows=nrows_num, ncols=ncols_num, figsize=(18, 12))
plt_df[['x_label', 'y_var1']].plot(x='x_label', ax=axes[0, 0])
plt_df[['x_label', 'y_var2']].plot(x='x_label', ax=axes[0, 1])
plt_df[['x_label', 'y_var3']].plot(x='x_label', ax=axes[0, 2])
plt_df[['x_label', 'y_var4']].plot(x='x_label', ax=axes[1, 0])
plt_df[['x_label', 'y_var5']].plot(x='x_label', ax=axes[1, 1])
plt_df[['x_label', 'y_var6']].plot(x='x_label', ax=axes[1, 2])

# x軸の項目名を斜めにしたい
for ax in axes.flatten():
    plt.setp(ax.get_xticklabels(), rotation=60)

# グラフを表示
plt.show()

※こちらはtickerの処理は不要です

このラベルが消えてしまう現象も色々確認したところ、
別端末ではラベルを"あああ~"ではなく1, 2, 3、と整数にしていました。

これは推測ですが、元々のラベルが1, 1.25, 1.5, ...とかのため
1, 2, 3ではラベルが設定されなかった(デフォルトのまま変更されなかった)のではないかと。

なのでラベルが数値とかでうまく表示されない方はsetpの方を使用していただいて、
文字列の方はset_xticklabelsを使用していただく、という感じかと思います。

 
すみません、matplotlibは思いの外根が深いと感じましたので
この記事はここで終了とさせていただきます。

4
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2