图例中误差条-Pandas柱形图

9

是否可以在图例中显示误差条?
(就像我用红色绘制的那样)
它们不一定要是正确的长度,只要它们被指示并且可识别即可。

我的工作示例:

import pandas as pd
import matplotlib.pyplot as plt
 
test  = pd.DataFrame(data={'one':2000,'two':300,'three':50,'four':150}, index=['MAX'])
fig, ax = plt.subplots(figsize=(5, 3), dpi=230) 
ax.set_ylim(-.12,.03)
# barplot
ax = test.loc[['MAX'],['one']].plot(position=5.5,color=['xkcd:camo green'], xerr=test.loc[['MAX'],['two']].values.T, edgecolor='black',linewidth = 0.3, error_kw=dict(lw=1, capsize=2, capthick=1),ax=ax,kind='barh',width=.025)
ax = test.loc[['MAX'],['one']].plot(position=7,color=['xkcd:moss green'], xerr=test.loc[['MAX'],['three']].values.T, edgecolor='black',linewidth = 0.3, error_kw=dict(lw=1, capsize=2, capthick=1),ax=ax,kind='barh',width=.025)
ax = test.loc[['MAX'],['one']].plot(position=8.5,color=['xkcd:light olive green'],xerr=test.loc[['MAX'],['four']].values.T,  edgecolor='black',linewidth = 0.3, error_kw=dict(lw=1, capsize=2, capthick=1),ax=ax,kind='barh',width=.025)
    
#  Legende
h0, l0 = ax.get_legend_handles_labels() 
l0 = [r'MAX $1$', r'MAX $2$', r'MAX $3$']
legend = plt.legend(h0, l0, borderpad=0.15,labelspacing=0.1,  frameon=True, edgecolor="xkcd:black", ncol=1, loc='upper left',framealpha=1, facecolor='white') 
legend.get_frame().set_linewidth(0.3)   

cur_axes = plt.gca()
cur_axes.axes.get_yaxis().set_ticklabels([]) 
cur_axes.axes.get_yaxis().set_ticks([]) 
plt.show()

enter image description here

我尝试了几种方法,但都没有成功。使用legend_elements中的Patch函数无法获得误差条线条,使用errorbar()函数可以绘制带有误差条的图形,但似乎无法在图例中使用:

import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.patches import Patch
from matplotlib.lines import Line2D 


legend_elements = [
    Line2D([1,2], [5,4], color='b', lw=1, label='Line'),  
    Patch(facecolor='orange', edgecolor='r', label='Color Patch'),
    matplotlib.pyplot.errorbar(3, 3, yerr=None, xerr=1, marker='s',mfc='xkcd:camo green', mec='black', 
                               ms=20, mew=2, fmt='-', ecolor="black", elinewidth=2, capsize=3, 
                               barsabove=True, lolims=False, uplims=False, xlolims=False, xuplims=False, 
                               errorevery=2, capthick=None, label="error"),
                  ]


 
test  = pd.DataFrame(data={'one':2000,'two':300,'three':50,'four':150}, index=['MAX'])
fig, ax = plt.subplots(figsize=(5, 3), dpi=230) 
ax.set_ylim(-.12,.03)
# barplot
ax = test.loc[['MAX'],['one']].plot(position=5.5,color=['xkcd:camo green'],       xerr=test.loc[['MAX'],['two']].values.T, edgecolor='black',linewidth = 0.3, error_kw=dict(lw=1, capsize=2, capthick=1),ax=ax,kind='barh',width=.025)
ax = test.loc[['MAX'],['one']].plot(position=7,color=['xkcd:moss green'],       xerr=test.loc[['MAX'],['three']].values.T,      edgecolor='black',linewidth = 0.3, error_kw=dict(lw=1, capsize=2, capthick=1),ax=ax,kind='barh',width=.025)
ax = test.loc[['MAX'],['one']].plot(position=8.5,color=['xkcd:light olive green'],xerr=test.loc[['MAX'],['four']].values.T,  edgecolor='black',linewidth = 0.3, error_kw=dict(lw=1, capsize=2, capthick=1),ax=ax,kind='barh',width=.025)
    
#  Legende
h0, l0 = ax.get_legend_handles_labels() 
l0 = [r'MAX $1$', r'MAX $2$', r'MAX $3$']
legend = plt.legend(h0, l0, borderpad=0.15,labelspacing=0.1,  frameon=True, edgecolor="xkcd:black", ncol=1, loc='upper left',framealpha=1, facecolor='white') 
legend.get_frame().set_linewidth(0.3)   


ax.legend(handles=legend_elements, loc='center')


cur_axes = plt.gca()
cur_axes.axes.get_yaxis().set_ticklabels([]) 
cur_axes.axes.get_yaxis().set_ticks([]) 
#plt.show()

enter image description here

基于r初学者的想法实现:
import pandas as pd
import matplotlib.pyplot as plt
 
test  = pd.DataFrame(data={'one':2000,'two':300,'three':50,'four':150}, index=['MAX'])
fig, ax = plt.subplots(figsize=(5, 3), dpi=150) 
ax.set_ylim(0, 6)
ax.set_xlim(0, 2400) 

ax1 = ax.twiny()
ax1.set_xlim(0, 2400)
ax1.set_xticks([])

ax.barh(1, width=test['one'], color=['xkcd:camo green'],        edgecolor='black',linewidth = 0.3, label='MAX1')
ax.barh(2, width=test['one'], color=['xkcd:moss green'],        edgecolor='black',linewidth = 0.3, label='MAX2')
ax.barh(3, width=test['one'], color=['xkcd:light olive green'], edgecolor='black',linewidth = 0.3, label='MAX3') 

ax1.errorbar(test['one'], 1, xerr=test['two'],   color='k', ecolor='k', fmt=',', lw=1, capsize=2, capthick=1, label='MAX1')
ax1.errorbar(test['one'], 2, xerr=test['three'], color='k', ecolor='k', fmt=',', lw=1, capsize=2, capthick=1, label='MAX2')
ax1.errorbar(test['one'], 3, xerr=test['four'],  color='k', ecolor='k', fmt=',', lw=1, capsize=2, capthick=1, label='MAX3')

handler, label   = ax.get_legend_handles_labels()
handler1, label1 = ax1.get_legend_handles_labels()
label1 = ['' for l in label1] 

ax.legend(handler,   label,  loc='upper left', handletextpad=1.5)
ax1.legend(handler1, label1, loc='upper left', handletextpad=1., markerfirst=False, framealpha=0.001)  
plt.show()

enter image description here

变更:

  • ax1获得与ax相同的限制
  • 删除所有来自label1的字符串
  • ax1.legend()中,处理程序和标签的顺序被交换,并且使用handlertextpad将误差线向右移动

2
为什么您想在图例中添加误差条? - igrinis
因为这个图形是关于误差线而不是柱状图的。 - kolja
这次我对传说有了更多的了解。如果我能够组合容器对象,那么我就不必将其制作成两个轴。谢谢。 - r-beginners
我会考虑其他展示信息的方式,比如盒状图或范围图。 - igrinis
2个回答

2

我想到的方法是使用“ax.barh”和“ax1.errorbar()”绘制图形,然后将每个图例重叠在一起。在其中一侧,我最小化了透明度,以便下面的图例可见;误差棒看起来不同,因为我将其制作成双轴。

import pandas as pd
import matplotlib.pyplot as plt
 
test  = pd.DataFrame(data={'one':2000,'two':300,'three':50,'four':150}, index=['MAX'])
fig, ax = plt.subplots(figsize=(5, 3), dpi=230) 
ax.set_ylim(0, 15)
ax.set_xlim(0, 2400)

ax1 = ax.twiny()
ax.barh(5.5, width=test['one'], color=['xkcd:camo green'], edgecolor='black',linewidth = 0.3, label='MAX1')
ax.barh(7.0, width=test['one'], color=['xkcd:moss green'], edgecolor='black',linewidth = 0.3, label='MAX2')
ax.barh(8.5, width=test['one'], color=['xkcd:light olive green'], edgecolor='black',linewidth = 0.3, label='MAX3')

ax1.errorbar(test['one'], 5.5, xerr=test['two'], color='k', ecolor='k', capsize=3, fmt='|', label='MAX1')
ax1.errorbar(test['one'], 7.0, xerr=test['three'], color='k', ecolor='k', capsize=3, fmt='|', label='MAX2')
ax1.errorbar(test['one'], 8.5, xerr=test['four'], color='k', ecolor='k', capsize=3, fmt='|', label='MAX3')

handler, label = ax.get_legend_handles_labels()
handler1, label1 = ax1.get_legend_handles_labels()

ax.legend(handler, label, loc='upper left', title='mix legend')
ax1.legend(handler1, label1, loc='upper left', title='mix legend', framealpha=0.001)
plt.show()

enter image description here


使用ax1.errorbar()是个好主意,但是我们不常用双轴误差线的显示方式。我采纳了你的想法并将其应用在我的示例中。谢谢! - kolja

1
您可以在图表上手动添加线条,调整您喜欢的颜色、粗细和位置。这是一种非常手动和费力的解决方案,但应该能够起作用。
# Draw line

import matplotlib.lines as ln
import numpy as np
 
# new clear axis overlay with 0-1 limits
ax2 = plt.axes([0,0,1,1], facecolor=(1,1,1,0))

x1,y1 = np.array([[0.18, 0.21], [0.831, 0.831]])
line1 = ln.Line2D(x1, y1, lw=1, color='black', alpha=1)

x2,y2 = np.array([[0.18, 0.21], [0.783, 0.783]])
line2 = ln.Line2D(x2, y2, lw=1, color='black', alpha=1)

x3,y3 = np.array([[0.18, 0.21], [0.732, 0.732]])
line3 = ln.Line2D(x3, y3, lw=1, color='black', alpha=1)

ax2.add_line(line1)
ax2.add_line(line2)
ax2.add_line(line3)

plt.show()

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接