Unit 09.02: Annotating in data coordinates
An annotation anchored in data coordinates stays on the point it describes.
Data coordinates, not pixels
An arrow anchored to a specific week and value, with a target line.
The code places both and reports where they are anchored.
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
weeks = list(range(1, 15))
rate = [2.1, 2.0, 1.9, 2.2, 2.0, 1.8, 1.9, 2.1, 2.0, 1.9, 2.3, 3.4, 3.1, 2.2]
fig, ax = plt.subplots()
ax.plot(weeks, rate)
ax.annotate("supplier change", xy=(12, 3.4), xytext=(7, 3.2),
arrowprops={"arrowstyle": "->"})
ax.axhline(2.0, linestyle="--", linewidth=1)
annotation = ax.texts[0]
print(f"annotation text : {annotation.get_text()!r}")
print(f"anchored at data : {annotation.xy}")
print(f"label sits at data: {annotation.get_position()}")
print(f"target line at y : {ax.lines[1].get_ydata()[0]}")
plt.close(fig)
print("\nAnchoring in DATA coordinates means the arrow stays on week 12 when")
print("the figure is resized. Anchoring in pixels means it drifts off.")
The annotation is anchored at week 12 in data terms, so it stays there when the figure is resized for a slide, a report or a phone. Anchored in pixels or in fractions of the axes, it drifts.
The target line is the other half of the same idea: drawn at a data value rather than at a position, so it remains correct if the axis limits change.
The mistake this prevents
The mistake is positioning annotations by eye and then resizing the figure for a different medium. Everything moves, and the arrow that pointed at the spike now points beside it - which is worse than no annotation.
Takeaway
Anchor annotations and reference lines in data coordinates. They then survive resizing, which every figure eventually undergoes.
