読者です 読者をやめる 読者になる 読者になる

ami_GS's diary

情報系大学院生の備忘録。ネットワークの勉強にハマっています。

matplotlibでboxplotの調べたことまとめ

Python matplotlib

はじめに

久しぶりです。研究やら授業でてんてこ舞いでした。

研究のためにboxplotで試行錯誤した結果のまとめを書こうと思います。



グループ化、及びbox内の塗りつぶし

普通にプロットすると、全部同じ色になってしまいます。
1つのグループに対し、複数のデータ群がある場合、同じ色だけで表現するのは非常に見難くなります。
なので、グループ毎にbox内を塗りつぶしてプロットしてみましょう。

今回は、3つの国にある、バナナ(黄色)ときゅうり(緑)の長さを例にしましょうかね、値は適当です。

from matplotlib import pyplot as plt
from scipy import stats

data = []
with open('./lengthData.txt', 'r') as f:
    for line in f.readlines():
        data.append(map(int, line.split())) # テキストデータから数値に変換してdataに格納

groupData = []
for i in range(3):
    tmpData = []
    for j in range(2):
        tmpData.append(data[i*2+j])  #(例えば) 3行2列の配列を作ります
    groupData.append(tmpData) #3サンプルそれぞれが2つのデータ群を持つ配列の完成

for i in range(3):
    #添字iでグループ指定、patch_artistはbox内の塗りつぶしです。
    #1グループの描画
    bp = plt.boxplot(groupData[i], positions=[2*i+1,2*i+2], widths=0.8, patch_artist=True) 
    bp['boxes'][0].set_facecolor('yellow') #黄色(バナナ)
    plt.setp(bp['medians'][0], color='red', linewidth=2) #メディアン
    plt.setp(bp['caps'][0], linewidth=1.5) #はこ髭の上限の線の太さ
    plt.setp(bp['caps'][1], linewidth=1.5) #はこ髭の下限の線の太さ
    plt.setp(bp['whiskers'][0], linewidth=2) #boxから伸びる上の点線の太さ
    plt.setp(bp['whiskers'][1], linewidth=2) #boxから伸びる下の点線の太さ

    bp['boxes'][1].set_facecolor('green') #緑(きゅうり)
    plt.setp(bp['medians'][1], color='red', linewidth=2)
    plt.setp(bp['caps'][2], linewidth=1.5) #同上(添字に注意!)
    plt.setp(bp['caps'][3], linewidth=1.5)
    plt.setp(bp['whiskers'][2], linewidth=2)
    plt.setp(bp['whiskers'][3], linewidth=2)

レジェンドを付ける

boxplotではデフォルトでレジェンドを付けることは出来ません。
(デフォルトのプロットの色が全部同じだから)
せっかく前節で色を付けたので、レジェンドを付けてみましょう。

banana, = plt.plot([1,1], 'y-', linewidth=10) #実際に線をプロットします。
cucumber, = plt.plot([1,1], 'g-', linewidth=10)

plt.legend((banana, cucumber), ('banana', 'cucumber')) #レジェンドの表示
banana.set_visible(False) #プロットした線を見えなくします。
cucumber.set_visible(False)

一度プロットしてからレジェンドを表示し、プロットした線を見えなくする、という手順です。




細かい設定

その他、プロットを見やすくするための設定です。

plt.ylim(0,40)
plt.yticks([i*20 for i in range(5)], ['0','10','20','30','40'], fontsize=17)
plt.ylabel('Length', fontsize=18)
plt.xticks([i for i in range(8)], ['','JP', 'JP', 'US', 'US', 'UK', 'UK', ''], fontsize=20)
plt.xlabel('Country', fontsize=18)
plt.grid()


以上の設定でプロットしたものが以下になります。
f:id:ami_GS:20140704103028j:plain