adjust_text: set label distance to a line

Viewed 66

I have the following dataframe:

d = {'a': [2, 3, 4.5], 'b': [3, 2, 5]}
df = pd.DataFrame(data=d, index=["val1", "val2","val3"])
df.head()
        a  b
val1  2.0  3
val2  3.0  2
val3  4.5  5

I plotted this dataframe with the following code:

fig, ax=plt.subplots(figsize=(10,10))


ax.scatter(df["a"], df["b"],s=1)



x1=[0, 2512]
y1=[0, 2512]


ax.plot(x1,y1, 'r-')


#set limits:
ax = plt.gca()
ax.set_xlim([0, 10])
ax.set_ylim([0, 10])


#add labels:

TEXTS = []
for idx, names in enumerate(df.index.values):
    x, y = df["a"].iloc[idx], df["b"].iloc[idx]
    TEXTS.append(ax.text(x, y, names, fontsize=12));

# Adjust text position and add lines 
adjust_text(
    TEXTS, 
    expand_points=(2.5, 2.5),
    expand_text=(2.5,2),
    autoalign="xy", 
    arrowprops=dict(arrowstyle="-", lw=1),
    ax=ax
);

enter image description here

However, I can not find a way to push the labels away from the red diagonal line, in order to get this result:

enter image description here

1 Answers

You can use the regular matplotlib annotate function and change the direction of the offset depending on the position of the data point relative to the red line:

ax = df.plot.scatter('a', 'b')
ax.set_aspect(1)
ax.plot((0,10), (0,10), 'r-')

offset = np.array([-1, 1])
for s, xy in df.iterrows():
    xy = xy.to_numpy()
    direction = 1 if xy[1] > xy[0] else -1
    ax.annotate(s, xy, xy + direction * offset, ha='center', va='center', arrowprops=dict(arrowstyle='-', lw=1))

enter image description here

Related