LoginSignup
0
0

More than 3 years have passed since last update.

binned errorbar plot with matplotlib: for log-log scale axes

Last updated at Posted at 2021-04-04

目的

左図のような散布図が描ける状況で, 右の図をmatplotlibなどで作成する手順を紹介すること.

test_scatter_log.pngtest_log.png

右図では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())
output
         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())
output
         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 エラーバー付きのグラフを描く
plt.errorbarの使い方と1次関数によるfittingの例があります.

Matplotlibで綺麗な論文用のグラフを作る
plt.rcParams['hoge']を使ってmatplotlibのデフォルト設定から変更を加えることで, 見栄えをよくすることができます.

0
0
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
0
0