Search code examples
pythonmatplotlibgraphing

Line on a python graph doesn't connect each point chronologically


I've made a graph that plots the change in the price of a ticket with the dates being on the x-axis and the ticket price being on the y-axis. For some reason, the line that connects the point starts at the first point, goes to the last point and then looks like it connects back to the other two points instead of connecting chronologically by date. This seems like a simple issue to fix, but I can't tell what I'm doing wrong from looking at my code as I'm still very new to using matplotlib. Here is the snippet of code that makes the graph:

fig, ax = plt.subplots()
ax.xaxis_date()
# Set date format and major locator of x-axis
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%m'+ '/' '%d' + '/' '%Y'))
plt.gca().yaxis.set_major_locator(mdates.DayLocator())
graph = fig.add_subplot(111)
xs = [x[0] for x in rows]
ys = [y[1] for y in rows]

plt.plot(xs,ys, 'r-o')
plt.gcf().autofmt_xdate()
graph.set_xticks(xs)
plt.title("Ticket Prices over the course of a month")
plt.xlabel("Date")
plt.ylabel("Ticket Price")  

Based on the code, what could be causing the problem? An image of the graph is below:

enter image description here


Solution

  • This could happen if the xs are not in date-sorted order. If that is indeed the problem, you could fix it by using argsort to sort xs and ys:

    idx = np.argsort(xs)
    xs = np.array(xs)[idx]
    ys = np.array(ys)[idx]
    

    For example,

    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.dates as mdates
    import datetime as DT
    
    rows = [(DT.date(2015,9,2), 25),
            (DT.date(2015,9,11), 35),
            (DT.date(2015,9,9), 30),
            (DT.date(2015,9,5), 27),]
    fig, ax = plt.subplots()
    
    xs = [x[0] for x in rows]
    ys = [y[1] for y in rows]
    idx = np.argsort(xs)
    xs = np.array(xs)[idx]
    ys = np.array(ys)[idx]
    
    plt.plot(xs,ys, 'r-o')
    fig.autofmt_xdate()
    ax.set_xticks(xs)
    ax.xaxis_date()
    # Set date format and major locator of x-axis
    ax.xaxis.set_major_formatter(mdates.DateFormatter('%m/%d/%Y'))
    ax.yaxis.set_major_locator(mdates.DayLocator())
    
    plt.title("Ticket Prices over the course of a month")
    plt.xlabel("Date")
    plt.ylabel("Ticket Price")  
    plt.show()
    

    yieldsenter image description here


    Note that if you use

    fig, ax = plt.subplots()
    

    then you could replace plt.gca() with ax, since plt.gca() returns the current axes. And similarly, you can replace plt.gcf() with fig since plt.gcf() returns the current figure.

    And you probably should not call graph = fig.add_subplot(111) since this overlays a second axes on top of ax. There is no need to set tick marks on graph

    graph.set_xticks(xs)
    

    as well as on ax, since this leads to two sets of tick marks on the x-axis.