lucky1928
lucky1928

Reputation: 8841

matplotlib - annotation line not match start and end point exactly

Say below example code, the annotation line not match the start and end point exactly:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

def annotate_delta(ax,df0,colname,col0,col1):
    x = col1
    y0 = df0[colname].iloc[col0]
    y1 = df0[colname].iloc[col1]
    d = 0.05
    ax.annotate('',
                 xy=(x+d, y0),
                 xytext=(x+d, y1),
                 xycoords='data',
                 textcoords='data',
                 arrowprops=dict(arrowstyle='|-|',facecolor='red',color='r'),
                 annotation_clip=False)   
    ax.annotate('%.1f'%(y1-y0),
                 xy=(x+d+0.15, (y1+y0)/2),
                 color='r',ha='center',
                 va='center',
                 rotation=-90
                 ,annotation_clip=False)        
    return

def plotme(df0,label):
    fig = plt.figure(figsize=(12,6))
    ax1 = fig.add_subplot(111)
    xcol = 'A'
    ycol = 'B'
    df.plot(x=xcol,y=ycol,ax=ax1,marker='.')
    annotate_delta(ax1,df0,ycol,0,len(df0)-1)    

    ax1.set_xticks(np.arange(len(df0)))
    ax1.set_xticklabels(df0[xcol],rotation=45, ha='right')
    plt.tight_layout()
    ax1.grid(axis='y')
    ax1.spines['right'].set_visible(False)
    ax1.spines['top'].set_visible(False)
    plt.xlabel("X")
    plt.ylabel("Y")
    fig.savefig("demo.png", dpi=fig.dpi)
    return

df = pd.DataFrame({'A':['apple','orange','bananna','watermelon'],'B':[1,3.5,2.5,4]})
plotme(df,"Sample")

enter image description here

Upvotes: 1

Views: 205

Answers (1)

tdy
tdy

Reputation: 41327

Arrow annotations are shrunk by 2 points by default:

shrinkA: default is 2 points
shrinkB: default is 2 points

Set shrinkA=0 and shrinkB=0 in arrowprops to remove the default padding:

arrowprops=dict(arrowstyle='|-|',color='r',shrinkA=0,shrinkB=0)

after resetting shrinkA and shrinkB

Upvotes: 2

Related Questions