Вы спрашиваете довольно много вещей.
- Чтобы получить линию сверху бара, кажется, что мы должны сначала нарисовать бары, а затем линию. Рисование последней линии сжимает xlims, поэтому мы должны применять их явно.
- Перемещение легенды более сложное. Обычно вы просто делаете
ax1.legend(loc='upper left')
, но в нашем случае с двумя графиками это, кажется, всегда рисует вторую легенду с последним нарисованным графиком в качестве единственной записи. - Есть функция
set_bbox_to_anchor
с небольшим документация . Он определяет некоторый блок (x, y, ширина, высота) , но есть также, казалось бы, недоступный параметр loc
, который управляет связью блока и позиции. «По умолчанию для loc
является loc="best"
, что дает непредсказуемые результаты при использовании аргумента bbox_to_anchor». Некоторые эксперименты могут быть необходимы. Лучшее решение, это охранять - Настройка текста проста. Просто переберите позиции y. Поместите в положение x 0,1,2, .. и по центру по горизонтали (вертикально внизу).
- Чтобы удалить шипы, кажется, что есть две оси друг над другом (что, вероятно, также вызывает
zorder
не работать как хотелось). Вы захотите скрыть шипы обоих из них. - Чтобы удалить галочки, используйте
ax1.axes.yaxis.set_ticks([])
. - Чтобы переключить галочки ax2 влево, используйте
ax2.yaxis.tick_left()
.
import pandas as pd
from matplotlib import pyplot as plt
data = {'Year': {0: '2016', 1: '2017', 2: '2018', 3: '2019', 4: '2020'},
'Some': {0: 9, 1: 13, 2: 21, 3: 18, 4: 28},
'All': {0: 157, 1: 189, 2: 216, 3: 190, 4: 284},
'Ratio': {0: 0.05732484076433121,
1: 0.06878306878306878,
2: 0.09722222222222222,
3: 0.09473684210526316,
4: 0.09859154929577464}}
df = pd.DataFrame(data)
ax1 = df.plot(x="Year", y="All",
kind="bar",
)
for i, a in df.All.items():
ax1.text(i, a, str(a), ha='center', va='bottom', fontsize=18)
xlims = ax1.get_xlim()
ax2 = df.plot(x="Year", y="Ratio",
kind="line", linestyle='-', marker='o', color="orange", ax=ax1, secondary_y=True,
figsize=((24, 12))
)
ax2.set_xlim(xlims) # needed because the line plot shortens the xlims
# ax1.get_legend().set_bbox_to_anchor((0.03, 0.9, 0.1, 0.1)) # unpredictable behavior when loc='best'
# ax1.legend(loc='upper left') # in our case, this would create a second legend
ax1.get_legend().remove() # remove badly placed legend
handles1, labels1 = ax1.get_legend_handles_labels()
handles2, labels2 = ax2.get_legend_handles_labels()
ax1.legend(handles=handles1 + handles2, # create a new legend
labels=labels1 + labels2,
loc='upper left')
# ax1.yaxis.tick_right() # place the yticks for ax1 at the right
ax2.yaxis.tick_left() # place the yticks for ax2 at the left
ax2.set_ylabel('Ratio')
ax2.yaxis.set_label_position('left')
ax1.axes.yaxis.set_ticks([]) # remove ticks
for ax in (ax1, ax2):
for where in ('top', 'right'):
ax.spines[where].set_visible(False)
plt.show()
![plot](https://i.stack.imgur.com/nenKC.png)