如何使用 ax.legend() 为条形图的子图添加通用图例
how to add a common legend for subplots of bar charts with ax.legend()
不幸的是,我已经尝试过不同的方法。我怎样才能为我的三个子图在图的顶部创建一个共同的图例?下面的代码没有工作,执行被卡住了,你还会在下面找到整个代码片段。其实我以为我一个人就可以搞定,但我确实需要你的帮助。
fig.tight_layout()
handles, labels = axs[0].get_legend_handles_labels()
fig.legend(handles, labels, fontsize=fs, loc='upper center', bbox_to_anchor=(0.5, 1.05), ncol=4)
这是我的整个代码片段:
df = pd.read_csv('energy_production_ver4.csv', sep=",")
# Figure Properties
fs = 4 # 30
lw = 2 # 3
width_bars=0.5
ec = 'dimgray'
# Create Subplots
fig, axs = plt.subplots(3, sharex=True, sharey=True, num=None, figsize=(25, 16), dpi=300, facecolor='w',
edgecolor='k') # 26 15
plt.rc('text', usetex=True)
plt.rc('font', family='serif')
plt.rc('font', size=fs-1)
plt.gcf().subplots_adjust(bottom=0.15)
#adjust Time Stamp to desired format
temp_x=df["DateTimeStamp"]
y1 = df['Production']
y2 = df['Consumption']
y3 = df['Production CHP 22kW']
y4 = df['Battery charge']
y5 = df['Battery discharge']
y6 = df['Grid supply']
y7 = df['Feed in grid']
# axs[0].grid(True, linestyle=':')
axs[0].yaxis.grid(linestyle=':')
axs[0].tick_params(axis='both', labelsize=fs)
axs[0].bar(temp_x, y1, label=r'$PV^\mathrm{s}$', color='blue', linewidth=lw / 2, width=width_bars)
axs[0].bar(temp_x, y2, label=r'$EV^\mathrm{s}$', color='orange', linewidth=lw / 2, width=width_bars)
axs[0].bar(temp_x, y3, label=r'CHP', color='green', linewidth=lw / 2, width=width_bars)
axs[0].set_ylabel(r'Energy in MWh', fontsize=fs)
axs[1].yaxis.grid(linestyle=':')
axs[1].tick_params(axis='both', labelsize=fs)
axs[1].bar(temp_x, y4, label=r'$BSS^\mathrm{CH}$', color='red', linewidth=lw / 2, width=width_bars)
axs[1].bar(temp_x, y5, label=r'$BSS^\mathrm{d}$', color='purple', linewidth=lw / 2, width=width_bars)
axs[1].set_ylabel(r'Energy in MWh', fontsize=fs)
axs[2].yaxis.grid(linestyle=':')
axs[2].tick_params(axis='both', labelsize=fs)
axs[2].bar(temp_x, y6, label=r'$GRID^\mathrm{CH}$', color='brown', linewidth=lw / 2, width=width_bars)
axs[2].bar(temp_x, y7, label=r'$GRID^\mathrm{d}$', color='pink', linewidth=lw / 2, width=width_bars)
axs[2].set_ylabel(r'Energy in MWh', fontsize=fs)
plt.xticks(rotation=90)
handles, labels = axs.get_legend_handles_labels() #does not work?
fig.legend(handles, labels, fontsize=fs, loc='upper center', bbox_to_anchor=(0.5, 1.05), ncol=4)
plt.show()
总体思路可行(我相信 this post or 是您的来源或适用于一个轴)。这里的问题是你有几个轴包裹在 axs
(这是一个 numpy 数组)所以当你做你写的东西时,你会得到类似
AttributeError: 'numpy.ndarray' object has no attribute 'get_legend_handles_labels'
解决这个问题的方法是遍历所有轴并连接图例(它们的标签和句柄),例如。通过以下方式:
...
handles,labels=[],[]
for ax in axs.flatten():
h, l = ax.get_legend_handles_labels()
handles+=h
labels+=l
fig.legend(handles, labels, fontsize=fs, loc='upper center', bbox_to_anchor=(0.5, 1.05), ncol=4)
不幸的是,我已经尝试过不同的方法。我怎样才能为我的三个子图在图的顶部创建一个共同的图例?下面的代码没有工作,执行被卡住了,你还会在下面找到整个代码片段。其实我以为我一个人就可以搞定,但我确实需要你的帮助。
fig.tight_layout()
handles, labels = axs[0].get_legend_handles_labels()
fig.legend(handles, labels, fontsize=fs, loc='upper center', bbox_to_anchor=(0.5, 1.05), ncol=4)
这是我的整个代码片段:
df = pd.read_csv('energy_production_ver4.csv', sep=",")
# Figure Properties
fs = 4 # 30
lw = 2 # 3
width_bars=0.5
ec = 'dimgray'
# Create Subplots
fig, axs = plt.subplots(3, sharex=True, sharey=True, num=None, figsize=(25, 16), dpi=300, facecolor='w',
edgecolor='k') # 26 15
plt.rc('text', usetex=True)
plt.rc('font', family='serif')
plt.rc('font', size=fs-1)
plt.gcf().subplots_adjust(bottom=0.15)
#adjust Time Stamp to desired format
temp_x=df["DateTimeStamp"]
y1 = df['Production']
y2 = df['Consumption']
y3 = df['Production CHP 22kW']
y4 = df['Battery charge']
y5 = df['Battery discharge']
y6 = df['Grid supply']
y7 = df['Feed in grid']
# axs[0].grid(True, linestyle=':')
axs[0].yaxis.grid(linestyle=':')
axs[0].tick_params(axis='both', labelsize=fs)
axs[0].bar(temp_x, y1, label=r'$PV^\mathrm{s}$', color='blue', linewidth=lw / 2, width=width_bars)
axs[0].bar(temp_x, y2, label=r'$EV^\mathrm{s}$', color='orange', linewidth=lw / 2, width=width_bars)
axs[0].bar(temp_x, y3, label=r'CHP', color='green', linewidth=lw / 2, width=width_bars)
axs[0].set_ylabel(r'Energy in MWh', fontsize=fs)
axs[1].yaxis.grid(linestyle=':')
axs[1].tick_params(axis='both', labelsize=fs)
axs[1].bar(temp_x, y4, label=r'$BSS^\mathrm{CH}$', color='red', linewidth=lw / 2, width=width_bars)
axs[1].bar(temp_x, y5, label=r'$BSS^\mathrm{d}$', color='purple', linewidth=lw / 2, width=width_bars)
axs[1].set_ylabel(r'Energy in MWh', fontsize=fs)
axs[2].yaxis.grid(linestyle=':')
axs[2].tick_params(axis='both', labelsize=fs)
axs[2].bar(temp_x, y6, label=r'$GRID^\mathrm{CH}$', color='brown', linewidth=lw / 2, width=width_bars)
axs[2].bar(temp_x, y7, label=r'$GRID^\mathrm{d}$', color='pink', linewidth=lw / 2, width=width_bars)
axs[2].set_ylabel(r'Energy in MWh', fontsize=fs)
plt.xticks(rotation=90)
handles, labels = axs.get_legend_handles_labels() #does not work?
fig.legend(handles, labels, fontsize=fs, loc='upper center', bbox_to_anchor=(0.5, 1.05), ncol=4)
plt.show()
总体思路可行(我相信 this post or axs
(这是一个 numpy 数组)所以当你做你写的东西时,你会得到类似
AttributeError: 'numpy.ndarray' object has no attribute 'get_legend_handles_labels'
解决这个问题的方法是遍历所有轴并连接图例(它们的标签和句柄),例如。通过以下方式:
...
handles,labels=[],[]
for ax in axs.flatten():
h, l = ax.get_legend_handles_labels()
handles+=h
labels+=l
fig.legend(handles, labels, fontsize=fs, loc='upper center', bbox_to_anchor=(0.5, 1.05), ncol=4)