I want to make a graph that contains bars, the value of the bars noted above them and a line on the secondary axis, but I can't configure the order of the elements the way I want where the bars would be the furthest element, followed by the line and then the texts, but so far I can only change the position of an entire axis and either the line goes over the text or is behind the bars.
import matplotlib.pyplot as plt
import seaborn as sns
years = [2019, 2020, 2021, 2022, 2023]
values1 = [1350, 1360, 1420, 1480, 1650]
values2 = [57, 62, 60.5, 59.7, 62.3]
fig, ax = plt.subplots(figsize=(6.2, 7.36), dpi = 150)
bars = ax.bar(years, values1)
heights = []
for bar in bars:
bar.set_zorder(2)
height = bar.get_height()
heights.append(height)
ax.annotate('{}'.format(round(height, 1)),
xy=(bar.get_x() + bar.get_width() / 2, height),
xytext=(0, 10), # 3 points vertical offset
textcoords="offset points",
ha='center', va='bottom',
fontsize = 20).set_zorder(1)
ax2 = ax.twinx()
lineplot = sns.lineplot(x = years, y = values2, ax = ax2, color="gray")
the graph that the code produces: graph with line in fort of text annotation
I tried changing the zorder on both axes and directly on the charts
Unfortunately respecting zorder across twinned axes is not possible. A workaround for annotations is to add them to the second axes, but using the data transform of the first. See the xycoords parameter added in the call to annotate here:
Note that this can be simplified by using the
bar_labelmethod, which is a convenience wrapper for adding annotations to bars: