I have a plot where I display the maximum and minimum points in the plot in different colors. Since the plot is dynamic, sometimes the text appears right on top of the ytick labels which does not look good. I want to keep the ytick's, so I thought of putting the text inside the plot.
However my x-axis is datetime variable, so providing the x,y position that is between the first and the second xtick is throwing me off.
I tried the solution here but its for the whole axis.
Based on the documentation I tried axis coords (0,0 is lower-left and 1,1 is upper-right) too, but the problem is that its difficult to come up with a proper pixel position that is both inside and top of the horizontal lines. Moreover I think it would be difficult to maintain since the data changes everyday.
I would like to stick to data coordinates since the data is dynamic.
Is it possible to do it using data coordinates?
Please use the following code I concocted for my situation -
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.transforms as transforms
x = ['2020-03-01', '2020-03-02', '2020-03-03', '2020-03-04', '2020-03-05']
y = [1,2,3,4,5.8]
df = pd.DataFrame({'X': x, 'Y': y})
fig, ax = plt.subplots()
sns.lineplot(x='X', y='Y', data=df)
show_point = 5.7
ax.axhline(show_point, ls='dotted')
trans = transforms.blended_transform_factory(ax.get_yticklabels()[0].get_transform(), ax.transData)
ax.text('2020-03-01', show_point, color="red", s=show_point, transform=trans, ha="right", va="bottom")
show_point2 = 1.7
ax.axhline(show_point2, ls='dotted')
trans = transforms.blended_transform_factory(ax.get_yticklabels()[0].get_transform(), ax.transAxes)
ax.text(0.05, 0.15, color="red", s=show_point2, transform=trans, ha="center", va="bottom")
plt.show()
EDIT 1
What it looks like now (in the real plot)-

Expected result -

The idea of using a blended coordinate system is correct. You can place the text at a y-coordinate in data coordinates and an x-coordinate in axes coordinates.
trans = transforms.blended_transform_factory(ax.transAxes, ax.transData)
ax.text(0.01, show_point, show_point, color="red", transform=trans, ha="left", va="bottom")
This particular blended transform is even built in, so you may also use
ax.text(0.01, show_point, show_point, color="red", transform=ax.get_yaxis_transform(),
ha="left", va="bottom")
You can avoid all the axis transformation stuff while still working in data coordinates if you use matplotlib.axes.Axes.annotate, something like this
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
x = ['2020-03-01', '2020-03-02', '2020-03-03', '2020-03-04', '2020-03-05']
y = [1,2,3,4,5.8]
df = pd.DataFrame({'X': x, 'Y': y})
fig, ax = plt.subplots()
sns.lineplot(x='X', y='Y', data=df)
show_point = 5.7
ax.axhline(show_point, ls='dotted')
ax.annotate(show_point, [ax.get_xticks()[0], show_point], va='bottom',
ha='right', color='red')
show_point2 = 1.7
ax.axhline(show_point2, ls='dotted')
ax.annotate(show_point2, [ax.get_xticks()[0], show_point2], va='bottom',
ha='right', color='red')
plt.show()
This will produce

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With