pythondatematplotlib

How to shorten the distance of two far apart date points in matplotlib?


I'm using pandas and matplotlib to plot a basketball team's performance in the last 20 seasons.

The code is fairly straightforward: plt.plot(date, performance) date is a list contains all the timestamp of the dates where a team plays, and performance is a corresponding list that contains that team's performance at that date.

The problem is that the team only plays at a certain time span in a year, for example, WNBA only plays from May to October every year. If I connect the data from the past many seasons together, there will be an undesirable long line across seasons that takes too long of a time span.

This is the two season plot, you can see this long line connecting two seasons

This is the plot starting from 1997, you can see the problem here: I can't express how the performance changes in a season since almost half of the timeline is occupied by the idle time between seasons

It'll work to some extent if I use string instead of timestamps for the x-axis. This is what I want But can I do it using date type? I want to shorten the distance of two date points between the end of the season and the start of the next season. Or how can I shorten the intervals of those idle months in a year and possibly lengthen the intervals of the active months?


Solution

  • Using the brokenaxes package (from, e.g., this answer), which is based on the Matplotlib broken axis example, and expanding on the brokenaxes datetime example, you could do something like:

    import matplotlib.pyplot as plt
    from brokenaxes import brokenaxes
    import numpy as np
    import datetime
    
    fig = plt.figure(figsize=(10, 5))
    
    xlims = []
    xx = []
    
    # create some fake data
    for year in range(1997, 2011):
        xx.extend([datetime.datetime(year, x, 1) for x in range(5, 11)])
        
        # set the extents of each part of the axis, i.e., between May and Oct each year
        xlims.append((datetime.datetime(year, 5, 1), datetime.datetime(year, 10, 1)))
    
    yy = np.random.randn(len(xx))
    
    # set the broken axes
    bax = brokenaxes(
        xlims=xlims,  # extents of each part of axis
        d=0,  # no diagonal tick
        wspace=0,  # no space between breaks
    )
    
    bax.plot(xx, yy)
    
    fig.autofmt_xdate()
    [x.remove() for x in bax.diag_handles]
    
    import matplotlib.dates as mdates
    for i, ax in enumerate(bax.axs):
        ax.set_xticks([xlims[i][0]])  # just add initial date for each year at the x-tick
        ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
    

    enter image description here