Search code examples
pythonlistmatplotlibplot

How to reorganize data to correctly lineplot in Python


I have the following code that plots ydata vs xdata which is supposed to be a circle. The plot has two subplots -- a lineplot with markers and a scatter plot.

import matplotlib.pyplot as plt


xdata = [-1.9987069285852805, -1.955030386765729, -1.955030386765729, -1.8259096357678795, -1.8259096357678795, -1.6169878720004491, -1.6169878720004491, -1.3373959790579202, -1.3373959790579202, -0.9993534642926399, -0.9993534642926399, -0.6176344077078071, -0.6176344077078071, -0.20892176376743077, -0.20892176376743077, 0.20892176376743032, 0.20892176376743032, 0.6176344077078065, 0.6176344077078065, 0.999353464292642, 0.999353464292642, 1.3373959790579217, 1.3373959790579217, 1.6169878720004487, 1.6169878720004487, 1.8259096357678786, 1.8259096357678786, 1.9550303867657255, 1.9550303867657255, 1.9987069285852832]
 
ydata = (0.0, -0.038801795445724575, 0.038801795445724575, -0.07590776623879933, 0.07590776623879933, -0.10969620340136318, 0.10969620340136318, -0.13869039009450249, 0.13869039009450249, -0.16162314123018345, 0.16162314123018345, -0.1774921855402276, 0.1774921855402276, -0.18560396964016201, 0.18560396964016201, -0.185603969640162, 0.185603969640162, -0.17749218554022747, 0.17749218554022747, -0.16162314123018337, 0.16162314123018337, -0.13869039009450224, 0.13869039009450224, -0.10969620340136294, 0.10969620340136294, -0.0759077662387991, 0.0759077662387991, -0.038801795445725006, 0.038801795445725006, 0.0)



fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16,6))
fig.suptitle('Plot comparison: line vs scatter'+ 3*'\n')
fig.subplots_adjust(wspace=1, hspace=3)
fig.supxlabel('x')
fig.supylabel('y')


ax1.plot(xdata, ydata, 'o-', c='blue')
ax1.set_title('Line-point plot', c='blue')

for i in range(len(xdata)):
   ax2.scatter(xdata, ydata, c='orange')
   ax2.set_title('Scatter plot', c='orange')
plt.savefig('line_vs_scatter_plot.png')
plt.show()

Output: enter image description here

From the output, it can be seen that the lineplot does not connect the dots (or points). Can we rearrange the x or y data in someway that fixes the issue? Or do something else?


Solution

  • If the xy coordinates have a consistent zig-zag pattern (odd/even), you could do :

    def unzigzag(data):
        data = list(data) # just in case
        return data[::2] + data[::-2] + [data[0]]
    
    ax1.plot(*map(unzigzag, [xdata, ydata]), "bo-")
    

    NB: This plot is annotated with the physical position (starting from 1) of x/y in their lists.

    enter image description here

    If not, one option would be to use :

    from shapely import MultiPoint
    from shapely.geometry.polygon import orient
    
    def unzigzag(x, y, ori=-1): # -1: clock-wise
        p = MultiPoint(list(zip(x, y))).convex_hull
        return list(orient(p, ori).boundary.coords)
    
    ax2.plot(*zip(*unzigzag(xdata, ydata)), "-bo") # the ori has no effect
    

    Animation to highlight the orientation :

    enter image description here