图例中的误差条 - 熊猫条形图

Posted

技术标签:

【中文标题】图例中的误差条 - 熊猫条形图【英文标题】:Errorbar in Legend - Pandas Bar Plot 【发布时间】:2020-10-22 11:02:43 【问题描述】:

是否可以在图例中显示误差线? (就像我画的一样) 它们不一定必须是正确的长度,如果它们被指示和识别,对我来说就足够了。

我的工作示例:

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()

我尝试了几种方法,没有一个有效。 使用 legend_elements 中的补丁,我没有得到错误栏的线条,使用 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()

基于以下思想的实现 初学者:

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()

变化:

ax1 获得与 ax 相同的限制 label1 中的所有字符串都被删除 在ax1.legend() 中,处理程序和标签的顺序被交换,handlertextpad 错误栏向右移动

【问题讨论】:

为什么要在图例中显示误差线? 因为该图是关于误差线而不是误差线。 这次我了解了更多关于传奇的信息。如果我可以组合容器对象,我就不必将它分成两个轴。谢谢。 我会考虑其他方式来呈现信息,例如箱形图或范围图。 【参考方案1】:

我想出的方法是绘制“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()

【讨论】:

ax1.errorbar() 好主意,但是双轴误差条的显示对我们来说并不常见。我用你的想法改编了我的例子。谢谢【参考方案2】:

您可以在图表上手动添加线条,调整您喜欢的颜色、粗细和位置。这是一个非常手动且费力的解决方案,但它应该可以工作。

# 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()

【讨论】:

以上是关于图例中的误差条 - 熊猫条形图的主要内容,如果未能解决你的问题,请参考以下文章

将水平线添加到 R 中 ggplot2 中的堆叠条形图,并在图例中显示

python使用matplotlib可视化误差条图使用errorbar函数可视化误差条形图自定义误差条图的颜色

熊猫数据框条形图在条形之间放置空间

分组条形图的子图分组图例

如何将值放在格条形图的条形图中并有图例

R语言ggplot2可视化因子分组并排条形图柱状图可视化添加误差条:barplot with several variables side by side grouped by a factor