python - 防止 Matplotlib Legend 在垂直子图上弄脏 h 填充?
问题描述
我有一个脚本,我在 5x1 的网格中绘制了几个变量。我注意到,当我的数据使我的图例更短时,子图本身具有可接受的高度和水平填充。当我的数据使我的图例更大(垂直)时,子图被压扁,在图之间留下额外的水平填充。
有没有办法防止这种情况?要将图例分配与轴对象分开并独立于图例间距绘制每个图?
下面是一个最小的可重现示例来说明我的意思:
#!/usr/bin/env python3
from pathlib import Path
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
def plotter(df, var_cols):
dfa = df.query("accepted == 'accepted'")
dfr = df.query("accepted != 'accepted'")
colors = {v: c for v, c in zip(['accepted', 'rejected', 'rerun'],
['darkgreen', 'firebrick', 'steelblue'])}
fig, axes = plt.subplots(nrows=len(var_cols), sharex=True)
for var, ax in zip(var_cols, axes):
for k, d in dfr.groupby('accepted'):
ax.scatter(d.iteration, d[var], label=k, alpha=0.8, c=d.accepted.map(colors))
ax.plot(dfa.iteration, dfa[var], '-o', label='accepted', color=colors['accepted'])
# Grab 3rd axes because I want the legend to be towards the center
handles, labels = axes[2].get_legend_handles_labels()
# Sort legend labels to put 'accepted' on top
labels, handles = zip(*sorted(zip(labels, handles), key=lambda t: t[0]))
axes[2].legend(handles, labels, markerscale=1.2, bbox_to_anchor=(1, 0.5))
fig.tight_layout()
def main():
states = {1: 'accepted', 2: 'rejected', 3: 'rerun'}
np.random.seed(666)
dat1 = pd.DataFrame({
'iteration': [0, 1, 2],
'accepted': ['accepted']*3,
'h_cap': [10.1, 6.5, 12.2],
'h_stor': [500, 410, 0],
'h_mark': [10, 6, 1],
'bid': [500, 100, 50],
'npv': [2.278, 2.6, 2.85]
})
dat2 = pd.DataFrame({
'iteration': range(10),
'accepted': [states[num] for num in np.random.randint(1, 4, size=10)],
'h_cap': np.random.rand(10),
'h_stor': np.random.rand(10),
'h_mark': np.random.rand(10),
'bid': np.random.rand(10),
'npv': np.random.rand(10)
})
var_cols = ['h_cap', 'h_stor', 'h_mark', 'bid', 'npv']
plotter(dat1, var_cols)
plt.savefig(Path('~/Desktop/nonsmushed.png').expanduser())
plotter(dat2, var_cols)
plt.savefig(Path('~/Desktop/smushed.png').expanduser())
if __name__ == '__main__':
main()
非糊状.png
smushed.png
解决方案
因为您的图例“属于” axes[2]
,tight_layout()
所以调整间距以使相邻轴不会覆盖图例。
fig.legend()
我认为最简单的解决方案是创建一个“图形级”图例tight_layout()
(如果需要,可以自动计算它,但这可能会变得混乱)
(...)
labels, handles = zip(*sorted(zip(labels, handles), key=lambda t: t[0]))
fig.legend(handles, labels, markerscale=1.2, bbox_to_anchor=(1, 0.5))
fig.tight_layout()
fig.subplots_adjust(right=0.75) # adjust value as needed
推荐阅读
- javascript - 在 onClick 属性中枚举存储在 state 中的函数数组
- angular - 在 Angular 中测试 AsyncValidators - 测试通过但不确定期望语句正在运行/执行
- php - 使用 PHP 在 GCS 上合并 CSV 文件
- batch-file - 如何获取公共 ipv4 而不是 ipv6
- docker - gitlab - 作曲家包的 ci
- visual-studio - ASP.NET Core Web API 控制器不返回正确的数据
- javascript - 使用多个 Bootstrap 折叠元素时定位特定的数据目标按钮?
- linq - LINQ 查询总是返回 Null
- python - 导入带有引号的奇怪格式的 csv
- flutter - Flutter`预期有1个位置参数,但找到了0个。`