pythonmatplotlibplot

Is there a way to connect the lines of a scatter+line plot with the ends of the markers, instead of the centers in Python?


I use this code to make a scatter+line plot with Matplotlib:

import matplotlib.pyplot as plt
    
zero = [1,2,3,4,5]
eq = [1.2,3,5,7,11]     
plt.plot(zero,'r_--', eq,'k_--',ms = 30, markeredgewidth=5)
plt.xlabel('Steps',fontsize=20, fontname='Helvetica', fontweight='bold')
plt.ylabel('Steps',fontweight='bold',fontsize=20, fontname='Helvetica')
plt.xticks([0,1,2,3,4], fontsize=20, fontname='Helvetica')
plt.yticks(fontsize =18, fontname='Helvetica')
plt.figure(figsize=(8,6))
plt.show()     
plt.close()

However, the lines in the resulting graph connect to the centers of the markers, as in the red example in the image. How can I get a result like the black example instead, where the lines connect to the endpoints of the markers?

Reference image


Solution

  • As per @J_H suggestion, you have to cheat a bit and -for each datapoint- introduce two datapoints corresponding to the ends of the markers.

    You can use the following list comprehensions to define the new datapoints

    import matplotlib.pyplot as plt
        
    zero = [1,2,3,4,5]
    eq = [1.2,3,5,7,11]
    
    # For each datapoint in your initial dataset, define two points, with same Y of the original point, and X values one slightly smaller and one slightly larger than the actual datapoint (i.e. x - offset and x + offset).
    offset = 0.175 # adjust the offset value manually or -better- based on marker size
    
    zeroX = [i
             for x in range(len(zero)) 
             for i in (x-offset, x+offset)]
    zeroY = [i
             for y in zero
             for i in (y, y)]
    eqX =   [i
             for x in range(len(eq)) 
             for i in (x-offset, x+offset)]
    eqY =   [i
             for y in eq 
             for i in (y, y)]
    
    plt.plot(zeroX, zeroY, eqX, eqY) # plot the lines without markers
    plt.plot(zero,'r_', eq,'k_',ms = 30, markeredgewidth=5) # plot the markers only 
    plt.xlabel('Steps',fontsize=20, fontname='Helvetica', fontweight='bold')
    plt.ylabel('Steps',fontweight='bold',fontsize=20, fontname='Helvetica')
    plt.xticks([0,1,2,3,4], fontsize=20, fontname='Helvetica')
    plt.yticks(fontsize =18, fontname='Helvetica')
    plt.show()     
    plt.close()
    

    and get the plot below as a result Plot with edge-connected markers

    As commented in the code, it would be better to have the offset automatically adjusted based on the marker size rather than manually.

    Hope this helps!