Хотя было бы определенно проще положиться на scipy
, я бы сделал это «вручную», то есть без него:
import matplotlib.pyplot as plt
import numpy as np
def mk_fork(x0,x1,y0,y1,new_level):
points=[[x0,x0,x1,x1],[y0,new_level,new_level,y1]]
connector=[(x0+x1)/2.,new_level]
return (points),connector
levels=[138, 219, 255, 268, 295]
locations=[(2, 5), (3, 4), (0, 3), (0, 1), (0, 2)]
label_map={
0:{'label':'BA','xpos':0,'ypos':0},
1:{'label':'FI','xpos':3,'ypos':0},
2:{'label':'MI','xpos':4,'ypos':0},
3:{'label':'NA','xpos':1,'ypos':0},
4:{'label':'RM','xpos':2,'ypos':0},
5:{'label':'TO','xpos':5,'ypos':0},
}
fig,ax=plt.subplots()
for i,(new_level,(loc0,loc1)) in enumerate(zip(levels,locations)):
print('step {0}:\t connecting ({1},{2}) at level {3}'.format(i, loc0, loc1, new_level ))
x0,y0=label_map[loc0]['xpos'],label_map[loc0]['ypos']
x1,y1=label_map[loc1]['xpos'],label_map[loc1]['ypos']
print('\t points are: {0}:({2},{3}) and {1}:({4},{5})'.format(loc0,loc1,x0,y0,x1,y1))
p,c=mk_fork(x0,x1,y0,y1,new_level)
ax.plot(*p)
ax.scatter(*c)
print('\t connector is at:{0}'.format(c))
label_map[loc0]['xpos']=c[0]
label_map[loc0]['ypos']=c[1]
label_map[loc0]['label']='{0}/{1}'.format(label_map[loc0]['label'],label_map[loc1]['label'])
print('\t updating label_map[{0}]:{1}'.format(loc0,label_map[loc0]))
ax.text(*c,label_map[loc0]['label'])
_xticks=np.arange(0,6,1)
_xticklabels=['BA','NA','RM','FI','MI','TO']
ax.set_xticks(_xticks)
ax.set_xticklabels(_xticklabels)
ax.set_ylim(0,1.05*np.max(levels))
plt.show()
Это главным образом основывается на создании словаря label_map
, который отображает исходные "местоположения" (т.е. (2,5)
) в "порядок xtick" (т.е. (4,5)
). «Форк» создается на каждом шаге i
с использованием mk_fork()
, который возвращает как points
(которые впоследствии соединяются на линейном графике), так и точку connector
, которая затем сохраняется как новые значения для 'xpos','ypos'
в пределах label_map
.
Я добавил несколько операторов print()
, чтобы подчеркнуть, что происходит на каждом шаге, и добавил .text()
, чтобы выделить местоположение каждого «соединителя».
Результат: