Volevo solo postare qui un'altra soluzione, una piccola biblioteca ho scritto per implementare questo tipo di cose: https://github.com/Phlya/adjustText Un esempio del processo può essere visto qui:
Ecco l'immagine di esempio :
import matplotlib.pyplot as plt
from adjustText import adjust_text
import numpy as np
together = [(0, 1.0, 0.4), (25, 1.0127692669427917, 0.41), (50, 1.016404709797609, 0.41), (75, 1.1043426359673716, 0.42), (100, 1.1610446924342996, 0.44), (125, 1.1685687930691457, 0.43), (150, 1.3486407784550272, 0.45), (250, 1.4013999168008104, 0.45)]
together.sort()
text = [x for (x,y,z) in together]
eucs = [y for (x,y,z) in together]
covers = [z for (x,y,z) in together]
p1 = plt.plot(eucs,covers,color="black", alpha=0.5)
texts = []
for x, y, s in zip(eucs, covers, text):
texts.append(plt.text(x, y, s))
plt.xlabel("Proportional Euclidean Distance")
plt.ylabel("Percentage Timewindows Attended")
plt.title("Test plot")
adjust_text(texts, only_move='y', arrowprops=dict(arrowstyle="->", color='r', lw=0.5))
plt.show()
Se si desidera una figura perfetta, si può smanettare un po. Innanzitutto, facciamo in modo che il testo respinga le linee: per questo creiamo solo un sacco di punti virtuali su di loro usando scipy.interpolate.interp1d.
Vogliamo evitare di spostare le etichette lungo l'asse x, perché, beh, perché non farlo per scopi illustrativi. Per questo usiamo il parametro only_move={'points':'y', 'text':'y'}
. Se vogliamo spostarli lungo l'asse x solo nel caso in cui si sovrappongano al testo, utilizzare move_only={'points':'y', 'text':'xy'}
. Inoltre, all'inizio la funzione sceglie l'allineamento ottimale dei testi rispetto ai loro punti originali, quindi vogliamo che ciò avvenga anche lungo l'asse y, quindi autoalign='y'
. Riduciamo anche la forza repulsiva dai punti per evitare che il testo voli troppo lontano a causa della nostra artificiale evasione delle linee. Tutti insieme:
from scipy import interpolate
p1 = plt.plot(eucs,covers,color="black", alpha=0.5)
texts = []
for x, y, s in zip(eucs, covers, text):
texts.append(plt.text(x, y, s))
f = interpolate.interp1d(eucs, covers)
x = np.arange(min(eucs), max(eucs), 0.0005)
y = f(x)
plt.xlabel("Proportional Euclidean Distance")
plt.ylabel("Percentage Timewindows Attended")
plt.title("Test plot")
adjust_text(texts, x=x, y=y, autoalign='y',
only_move={'points':'y', 'text':'y'}, force_points=0.15,
arrowprops=dict(arrowstyle="->", color='r', lw=0.5))
plt.show()
vedi anche http://stackoverflow.com/questions/14938541/how-to-improve-the-label-placement-for-matplotlib-scatter-chart-code- Algoritmo/15859652 # 15859652 – tacaswell