I'm trying to adapt the code presented here to better fit what I need. I have to display long annotations, so I'd like to show them starting from the "edge" of the stem line that is further in relation to the y axis, adding some space if the text gets on top of the vertical line. I think I can explain that by saying that instead of defining where the text starts, I'd like to set when it should end. I thought about just changing the ['top', 'bottom'] part of the code to ['bottom', 'top'], but that didn't quite work.
This is a reproducible sample code:
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.dates as mdates
from datetime import datetime
names = ['v2.2.4', 'v3.0.3', 'v3.0.2', 'v3.0.1', 'v3.0.0', 'v2.2.3',
'v2.2.2', 'v2.2.1', 'v2.2.0', 'v2.1.2', 'v2.1.1', 'v2.1.0',
'v2.0.2', 'v2.0.1', 'v2.0.0', 'v1.5.3', 'v1.5.2', 'v1.5.1',
'v1.5.0', 'v1.4.3', 'v1.4.2', 'v1.4.1', 'v1.4.0']
dates = ['2019-02-26', '2019-02-26', '2018-11-10', '2018-11-10',
'2018-09-18', '2018-08-10', '2018-03-17', '2018-03-16',
'2018-03-06', '2018-01-18', '2017-12-10', '2017-10-07',
'2017-05-10', '2017-05-02', '2017-01-17', '2016-09-09',
'2016-07-03', '2016-01-10', '2015-10-29', '2015-02-16',
'2014-10-26', '2014-10-18', '2014-08-26']
names = [name+"very_very_long_long" for name in names]
# Convert date strings (e.g. 2014-10-18) to datetime
dates = [datetime.strptime(d, "%Y-%m-%d") for d in dates]
# Choose some nice levels
levels = np.tile([-5, 5, -3, 3, -1, 1],
int(np.ceil(len(dates)/6)))[:len(dates)]
# Create figure and plot a stem plot with the date
fig, ax = plt.subplots(figsize=(8.8, 4), constrained_layout=True)
ax.set(title="Matplotlib release dates")
markerline, stemline, baseline = ax.stem(dates, levels,
linefmt="C3-", basefmt="k-",
use_line_collection=True)
plt.setp(markerline, mec="k", mfc="w", zorder=3)
# Shift the markers to the baseline by replacing the y-data by zeros.
markerline.set_ydata(np.zeros(len(dates)))
# annotate lines
vert = np.array(['bottom', 'top'])[(levels > 0).astype(int)]
for d, l, r, va in zip(dates, levels, names, vert):
ax.annotate(r, xy=(d, l), xytext=(-3, np.sign(l)*3),
textcoords="offset points", va=va, ha="right", rotation=90)
# format xaxis with 4 month intervals
# ax.get_xaxis().set_major_locator(mdates.MonthLocator(interval=4))
# ax.get_xaxis().set_major_formatter(mdates.DateFormatter("%b %Y"))
# plt.setp(ax.get_xticklabels(), rotation=30, ha="right")
# remove y axis and spines
ax.get_yaxis().set_visible(False)
for spine in ["left", "top", "right"]:
ax.spines[spine].set_visible(False)
# ax.margins(y=0.1)
plt.show()
I've been trying to use this lib , but so far it just creates a new whole mess cause I'm probably not using it properly.
I don't have much experience with this kind of graph, but I came up with two ideas: one is to place the string horizontally and position it at the top of the level. The other is to radically switch the axes and make it a vertical graph.
1)Horizontal and centered string
for d, l, r, va in zip(dates, levels, names, vert):
ax.annotate(r, xy=(d, l), xytext=(60, np.sign(l)*15),
textcoords="offset points", va=va, ha="right")
fig, ax = plt.subplots(figsize=(6, 12), constrained_layout=True)
# define bounding box
boxdic={'facecolor':'0.9',
'edgecolor':'0.6',
'boxstyle':'round',
'linewidth':1}
arrowprops = dict(
arrowstyle="->",
connectionstyle="angle,angleA=0,angleB=45,rad=10")
arrowprops1 = dict(
arrowstyle="->",
connectionstyle="angle,angleA=0,angleB=-45,rad=10")
ax = plt.axes(xlim=(-5,5), ylim=(datetime(2020,1,1,0,0), datetime(2014,1,1,0,0)))
ax.set(title="Matplotlib release dates")
ax.scatter([0]*len(dates), dates, marker='o', color='w', ec='k')
ax.spines['left'].set_position('zero')
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
ax.spines['bottom'].set_visible(False)
ax.axes.xaxis.set_visible(False)
for i, (d, n) in enumerate(zip(dates, names)):
if i % 2 == 0:
ax.annotate(str("{}".format(n)), xy=(0.1, d),
xycoords='data', xytext=(15, 25), textcoords='offset points',
color="k", fontsize=10, bbox=boxdic, arrowprops=arrowprops)
else:
ax.annotate(str("{}".format(n)), xy=(-0.1, d),
xycoords='data', xytext=(-15, 25), textcoords='offset points',
color="k", fontsize=10, bbox=boxdic, ha='right', arrowprops=arrowprops1)
months = mdates.MonthLocator(interval = 6)
months_fmt = mdates.DateFormatter('%Y-%m')
ax.yaxis.set_major_locator(months)
ax.yaxis.set_major_formatter(months_fmt)
plt.show()
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.