Issue
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
Solution
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:
import matplotlib.pyplot as plt
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)
ax2 = ax.twinx()
lineplot = ax2.plot(years, values2, ls="-", color="gray")
for bar in bars:
height = bar.get_height()
ax2.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,
xycoords=ax.transData)
plt.show()
Note that this can be simplified by using the bar_label
method, which is a convenience wrapper for adding annotations to bars:
import matplotlib.pyplot as plt
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)
ax2 = ax.twinx()
lineplot = ax2.plot(years, values2, ls="-", color="gray")
ax2.bar_label(bars, fontsize=20, padding=10, xycoords=ax.transData)
plt.show()
Answered By - RuthC
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.