Python でボックス プロットを使用する場合、各ボックス (または少なくとも中央値の数値) の上に中央値と分散の値を自動的に/簡単にオーバーレイする方法はありますか?
たとえば、下の箱ひげ図では、各箱ひげ図にテキスト (中央値、+- std) を重ねたいと思います。
Python でボックス プロットを使用する場合、各ボックス (または少なくとも中央値の数値) の上に中央値と分散の値を自動的に/簡単にオーバーレイする方法はありますか?
たとえば、下の箱ひげ図では、各箱ひげ図にテキスト (中央値、+- std) を重ねたいと思います。
boxplot 関数を使用して boxplot を描画すると仮定すると、グラフのコンポーネントを保持する辞書が返されます。ボックスは、標準偏差ではなく、内側の四分位範囲 (25 ~ 75 パーセンタイル) を表すことに注意してください。
>>> bp_dict = boxplot(data, vert=False) # draw horizontal boxplot
>>> bp_dict.keys()
>>> bp_dict.keys()
['medians', 'fliers', 'whiskers', 'boxes', 'caps']
これらには、各プロット要素を形成する Line2D オブジェクトが含まれています。Line2D.get_xydata メソッドを使用して中央値とボックスの位置 (データ座標) を取得し、テキストを配置する場所を特定できます。
from pylab import *
# from http://matplotlib.org/examples/pylab_examples/boxplot_demo.html
# fake up some data
spread= rand(50) * 100
center = ones(25) * 50
flier_high = rand(10) * 100 + 100
flier_low = rand(10) * -100
data =concatenate((spread, center, flier_high, flier_low), 0)
# fake up some more data
spread= rand(50) * 100
center = ones(25) * 40
flier_high = rand(10) * 100 + 100
flier_low = rand(10) * -100
d2 = concatenate( (spread, center, flier_high, flier_low), 0 )
data.shape = (-1, 1)
d2.shape = (-1, 1)
#data = concatenate( (data, d2), 1 )
# Making a 2-D array only works if all the columns are the
# same length. If they are not, then use a list instead.
# This is actually more efficient because boxplot converts
# a 2-D array into a list of vectors internally anyway.
data = [data, d2, d2[::2,0]]
# multiple box plots on one figure
figure()
# get dictionary returned from boxplot
bp_dict = boxplot(data, vert=False)
for line in bp_dict['medians']:
# get position data for median line
x, y = line.get_xydata()[1] # top of median line
# overlay median value
text(x, y, '%.1f' % x,
horizontalalignment='center') # draw above, centered
for line in bp_dict['boxes']:
x, y = line.get_xydata()[0] # bottom of left line
text(x,y, '%.1f' % x,
horizontalalignment='center', # centered
verticalalignment='top') # below
x, y = line.get_xydata()[3] # bottom of right line
text(x,y, '%.1f' % x,
horizontalalignment='center', # centered
verticalalignment='top') # below
show()
少し修正:
for line in bp_dict['medians']:
# get position data for median line
x, y = line.get_xydata()[1] # top of median line
# overlay median value
text(x, y, '%.1f' % x, horizontalalignment='center') # draw above, centered
for box in bp_dict['boxes']:
x, y = box.get_path().vertices[0] # bottom of left line
text(x, y, '%.1f' % x, horizontalalignment='center', # centered
verticalalignment='top') # below
x, y = box.get_path().vertices[6] # bottom of right line
text(x, y, '%.1f' % x,
horizontalalignment='center', # centered
verticalalignment='top') # below