目的
左図のような散布図が描ける状況で, 右の図をmatplotlibなどで作成する手順を紹介すること.
右図では5%, 95%percentileをerrorbarにして描画した. また, 挿入式における対数の底は10である. fittingは$x>10$の領域で行った.
環境
Python 3.9
Numpy 1.20.1
Pandas 1.2.0
Matplotlib 3.3.3
scikit-learn 0.24.1
方法
import
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.metrics import r2_score
データの概形
PandasのDataFrameで与えられているとする.
print(df.head())
x y
0 1.84734 18.54020
1 1.87387 8.96109
2 2.72002 41.01980
3 2.66678 18.63230
4 5.80852 47.13240
#例えば10の肩に乗る指数のbin幅を 1/bins=1/10 としたいとき. 線形の場合とは異なる
bins=10
df['logxbin']=10**(round(bins*np.log10(df.x))/bins)
#errorbarをpercentileで作る場合
m=df.groupby('logxbin').quantile(q=0.5)
lower=df.groupby('logxbin').quantile(q=0.05)
upper=df.groupby('logxbin').quantile(q=0.95)
#fitting. 線形の場合とは異なる
c=np.polyfit(np.log10(df.x[df.x>10]) ,np.log10(df.y[df.x>10]),1)
l=10**(c[0]*np.log10(m.index[m.index>10])+c[1])
r2=r2_score(l,m.y[m.index>10])
print(df.head())
x y logxbin
0 1.84734 18.54020 1.995262
1 1.87387 8.96109 1.995262
2 2.72002 41.01980 2.511886
3 2.66678 18.63230 2.511886
4 5.80852 47.13240 6.309573
plt.rcParams['font.family'] = 'Arial'
plt.rcParams['mathtext.fontset'] = 'stix'
plt.rcParams['font.size'] = 15
plt.rcParams['xtick.labelsize'] = 9
plt.rcParams['ytick.labelsize'] = 9
plt.rcParams['xtick.direction'] = 'in'
plt.rcParams['ytick.direction'] = 'in'
plt.rcParams['axes.linewidth'] = 0.7
plt.rcParams['axes.grid'] = False
plt.figure(figsize=(3,9/4))
plt.title('binned errorbar plot test: log', fontsize=13)
plt.xlabel('$x$')
plt.ylabel('$y$')
plt.xscale('log')
plt.yscale('log')
#errorbarの設定方法に注意. percentileを使うときこのように書く必要がある
plt.errorbar(m.index, m.y, yerr=[m.y-lower.y, upper.y-m.y], fmt='o', marker='s', mfc='#000000', mec='#000000',
ecolor='#2e3436', elinewidth=0.5, capsize=1.0, capthick=1.0)
plt.plot(m.index[m.index>10],l, color='#2e3436', linestyle=':', linewidth=0.7)
plt.text(2, 10**4, f'$\log(y)$={c[0]:.2f}$\log(x)$ + {c[1]:.2f}, \n$R^2$={r2:.2f}', fontsize=13)
plt.savefig('test_log.pdf', transparent=True, bbox_inches='tight')
背景
線形スケールでの場合に引き続き, 両対数スケールの散布図から横軸でbin分けして平均&標準偏差/percentileを用いて見栄えをすっきりさせる必要があった.
課題点
この右図に挿入した回帰式の底は10であるが, うまくスクリプト内で指定できなかった. また, figsizeで同じ数字を指定したにもかかわらず,以前作成したpngと異なるサイズの画像をsaveした. plt.savefigの振る舞いを調査中である.
リンク
以下の2リンクで勉強しました. 有難うございます.
[matplotlib エラーバー付きのグラフを描く] (https://qiita.com/yuto_ohno/items/d2676e04f2d94fc30248)
plt.errorbar
の使い方と1次関数によるfittingの例があります.
Matplotlibで綺麗な論文用のグラフを作る
plt.rcParams['hoge']
を使ってmatplotlibのデフォルト設定から変更を加えることで, 見栄えをよくすることができます.