LoginSignup
23
27

More than 3 years have passed since last update.

(matplotlib)グラフの体裁調整のためのTips【軸・図枠・目盛・目盛文字編】

Last updated at Posted at 2020-12-30

概要

matplotlibで生成したグラフの体裁調整・微調整のためのTips(~軸・図枠・目盛・目盛文字~編)です。
2.png

matplotlib 3.2.2、GoogleColab.(Python 3.6.9)により動作確認をしています。

準備・共通

グラフのなかで日本語が使えるように japanize-matplotlib ライブラリをインストールします。GoogleColab.の場合、コードセルで以下を実行することでインストールできます。

japanize-matplotlibのインストール(GoogleColab.)
!pip install japanize-matplotlib

各種ライブラリをインポートをします。

準備・共通コード
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import matplotlib.transforms as transforms
import matplotlib.patheffects as patheffects
import japanize_matplotlib
import numpy as np

基本形として、特に体裁調整していないグラフを出力してみます。

基本
x = np.linspace(-6,6,21)
y = 1/(1+np.exp(-x))
fig,ax = plt.subplots(figsize=(4,3),facecolor='white',dpi=150)
ax.plot(x,y,marker='.')
plt.show()

以下のようなグラフが出力できればOKです。

1.png

目盛文字(TickLabel)の書式設定

X軸の主目盛の書式を小数第1位まで表示する形式に、Y軸の主目盛の書式を「2.0×10-1のような形式」に設定してみます。

import matplotlib.ticker as ticker を忘れないように。

目盛文字の書式設定
x = np.linspace(-6,6,21)
y = 1/(1+np.exp(-x))
fig,ax = plt.subplots(figsize=(4,3),facecolor='white',dpi=150)
ax.plot(x,y,marker='.')

ax.xaxis.set_major_formatter(ticker.FuncFormatter(lambda x,_: f'{x:.1f}'))
ax.yaxis.set_major_formatter(ticker.FuncFormatter(lambda y,_: f'{y*10:.1f}'+ r'$\times 10^{-1}$'))

plt.show()

3.png

目盛文字(TickLabel)の位置調整

後述する方法で目盛を「内向き」に設定すると、X軸とY軸の目盛文字が近すぎて見苦しくなる場合があります。これを解決するために、X軸の主目盛の文字位置を下方向に微調整してみます。matplotlib.transforms as transforms を忘れないように。

目盛文字の位置調整
x = np.linspace(1000,1010,11)
y = (x-1000)*0.5

fig,axes = plt.subplots(1,2,figsize=(8,3),facecolor='white',dpi=150)
axes = axes.ravel()
for ax in axes:
  ax.plot(x,y,marker='.')
  ax.set_xlim(1000,1010)
  ax.set_ylim(0,5)
  ax.tick_params(direction='in')

# 右側(axes[1])のみ xticklabels 位置の調整
mv = transforms.ScaledTranslation(0,-0.07,fig.dpi_scale_trans)
for label in axes[1].xaxis.get_majorticklabels() :
    label.set_transform(label.get_transform() + mv)

axes[1].text(0.95,0.075,'x_tick_labels 位置の調整あり',ha='right',c='tab:red',transform=ax.transAxes)
plt.show()

もっと簡単に移動する方法がありました。

目盛文字の位置調整(更新版)
x = np.linspace(1000,1010,11)
y = (x-1000)*0.5

fig,axes = plt.subplots(1,2,figsize=(8,3),facecolor='white',dpi=150)
axes = axes.ravel()
for ax in axes:
  ax.plot(x,y,marker='.')
  ax.set_xlim(1000,1010)
  ax.set_ylim(0,5)
  ax.tick_params(direction='in')

# 右側(axes[1])のみ xticklabels 位置の調整
ax = axes[1]
ax.get_xaxis().set_tick_params(pad=8)
ax.text(0.95,0.075,'x_tick_labels 位置の調整あり',ha='right',c='tab:red',transform=ax.transAxes)

plt.show()

4.png

軸/図枠を非表示に設定

imshow(...) などを使用した場合、軸/図枠を表示させたくない場合があります。軸/図枠を非表示にしてみます。

軸/図枠を非表示
x = np.linspace(-6,6,21)
y = 1/(1+np.exp(-x))
fig,ax = plt.subplots(figsize=(4,3),facecolor='white',dpi=150)
ax.plot(x,y,marker='.')

for p in ['left','top','right','bottom']:
  ax.spines[p].set_visible(False)

ax.grid() # グリッド
plt.show()

5.png

目盛(Tick)の向きと長さを調整

軸の目盛の向きを「内側」「外側」「両側」に変更してみます。また、目盛の「長さ」を調整してみます。長さをゼロに設定すれば、実質的に目盛を非表示にすることができます。

目盛の向きと長さを調整
x = np.linspace(-6,6,21)
y = 10/(1+np.exp(-x))-5
fig,axes = plt.subplots(2,2,figsize=(8,6),facecolor='white',dpi=150)
axes = axes.ravel()

for ax in axes :
  ax.plot(x,y,marker='.')

axes[0].tick_params(direction='in')
axes[0].text(0.1,0.9,"direction='in'",c='tab:red',va='top',transform=axes[0].transAxes)
axes[1].tick_params(direction='inout')
axes[1].text(0.1,0.9,"direction='inout'",c='tab:red',va='top',transform=axes[1].transAxes)
axes[2].tick_params(direction='inout',length=8)
axes[2].text(0.1,0.9,"direction='inout'\nlength=8",c='tab:red',va='top',transform=axes[2].transAxes)
axes[3].tick_params(length=0)
axes[3].text(0.1,0.9,"length=0",c='tab:red',va='top',transform=axes[3].transAxes)

plt.show()

6.png

特定の目盛文字(TickLabel)だけ色を変更する

相手に注目してもらうために TickLabel のうち特定の項目だけ色を変えたい場合があります。ここでは、xticklabels の2番目の要素である Carol だけを赤文字にしてみます。

特定の目盛文字(TickLabel)だけ色を変更
x = ['Alice','Bob','Carol','Dave','Ellen']
y = [40,20,25,40,20]

fig,ax = plt.subplots(figsize=(4,3),facecolor='white',dpi=150)
bars = ax.bar(x,y)
bars[2].set_facecolor('tab:red') # おまけ:バーも赤色に変更
#print(type(bars[2])) # <class 'matplotlib.patches.Rectangle'>

labels = ax.get_xticklabels()
labels[2].set_color('tab:red') # 2番目の要素を赤文字に変更
#print(type(labels[2])) # <class 'matplotlib.text.Text'>

plt.show()

8.png

Y軸の上下を反転

Y軸の TickLabel は、デフォルトでは下から上に向かって並びます。これを、反転させ上から下に向かって並ぶようにしてみます。

Y軸の上下を反転
x = ['Alice','Bob','Carol','Dave','Ellen']
y = [40,20,25,40,20]

fig,axes = plt.subplots(1,2,figsize=(8,3),facecolor='white',dpi=150)
axes = axes.ravel()

for ax in axes:
  ax.barh(x,y)
  ax.tick_params(length=0)
  ax.grid(axis='x')
  ax.set_axisbelow(True)

axes[0].set_title('デフォルト(下から上)')
axes[1].set_title('反転(上から下)')

# 右図で上下を反転
ax = axes[1]
ax.invert_yaxis()
t = axes[1].text(0.95,0.05,'ax.invert_yaxis( )',c='tab:red',ha='right',transform=ax.transAxes)
t.set_path_effects([patheffects.Stroke(linewidth=3,foreground='white'),patheffects.Normal()])

plt.show()

11.png

Y軸の目盛ラベルの配置を調整(右揃え、左揃え、中央揃え)

Y軸の目盛ラベルの配置を調整(右揃え、左揃え、中央揃え)
x = ['A','BB','CCC']
y = [40,20,25]

fig,axes = plt.subplots(3,1,figsize=(4,4),facecolor='white',dpi=150)
axes = axes.ravel()

text=['右揃え(デフォルト)','左揃え','中央揃え']
for i, ax in enumerate(axes):
  ax.barh(x,y)
  ax.invert_yaxis()
  ax.tick_params(length=0)
  ax.set_xticklabels([])
  t = ax.text(0.95,0.1,text[i],c='tab:red',ha='right',transform=ax.transAxes)
  t.set_path_effects([patheffects.Stroke(linewidth=3,foreground='white'),patheffects.Normal()])

# 左揃え
ax = axes[1]
ax.set_yticklabels(x,ha ='left')
ax.get_yaxis().set_tick_params(pad=25)

# 中央揃え
ax = axes[2]
ax.set_yticklabels(x,ha ='center')
ax.get_yaxis().set_tick_params(pad=17.5)

plt.show()

10.png

X軸とY軸をゼロ位置にセット

数学の教科書に記載されているようなグラフスタイル(X軸とY軸の目盛文字が「ゼロ」の位置にある)に変更してみます。

X軸とY軸をゼロ位置にセット
x = np.linspace(-6,6,21)
y = 10/(1+np.exp(-x))-5  # 変更

fig,ax = plt.subplots(figsize=(4,3),facecolor='white',dpi=150)
ax.plot(x,y,marker='.')

ax.spines['bottom'].set_position('zero')
ax.spines['left'].set_position('zero')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.tick_params(direction='inout')

plt.show()

7.png

さらに、細かな調整を行ないます。

X軸とY軸をゼロ位置にセット2
x = np.linspace(-6,6,21)
y = 10/(1+np.exp(-x))-5  # 変更

fig,ax = plt.subplots(figsize=(4,4),facecolor='white',dpi=150)
ax.plot(x,y,marker='.')

ax.spines['bottom'].set_position('zero')
ax.spines['left'].set_position('zero')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)

ax.set_xlim(6,-6)
ax.set_ylim(6,-6)

# 主目盛:刻み間隔2、0は非表示、文字を白縁取り
ax.set_xticks(np.arange(-6,6+1,2))
labels = ax.set_xticklabels( [ ( x if x!=0 else '') for x in np.arange(-6,6+1,2)] )
for t in labels :
  t.set_path_effects([patheffects.Stroke(linewidth=3,foreground='white'),patheffects.Normal()])

ax.set_yticks(np.arange(-6,6+1,2))
labels = ax.set_yticklabels( [ ( y if y!=0 else '') for y in np.arange(-6,6+1,2)] )
for t in labels :
  t.set_path_effects([patheffects.Stroke(linewidth=3,foreground='white'),patheffects.Normal()])

ax.tick_params(which='major',direction='inout',length=5)

# 補助目盛(minor):刻み間隔1でグリッド描画するための準備
ax.set_xticks(np.linspace(-6,6,13),minor=True)
ax.set_yticks(np.linspace(-6,6,13),minor=True)
ax.tick_params(which='minor',direction='inout',length=3)

# グリッド(which='both'で、majorとminorの目盛位置にグリッド)
ax.grid(which='both')

plt.show()

2.png

関連

23
27
0

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
23
27