Search code examples
python-3.xnumpyscipysmoothing

Smooth a plot with uneven intervals on x-axis


How do I smooth a plot with my x-axis being dates of unequal interval. My data is;

import numpy as np
from pylab import plt
import datetime as dt

x = np.array([dt.date(2000, 11, 30), dt.date(2001, 3, 31), dt.date(2001, 11, 30),
                dt.date(2002, 3, 31), dt.date(2002, 11, 30), dt.date(2003, 3, 31),
                dt.date(2003, 11, 30), dt.date(2004, 3, 31), dt.date(2004, 11, 30),
                dt.date(2005, 3, 31), dt.date(2005, 11, 30), dt.date(2006, 3, 31),
                dt.date(2006, 11, 30), dt.date(2007, 3, 31), dt.date(2007, 11, 30),
                dt.date(2008, 3, 31), dt.date(2008, 11, 30), dt.date(2009, 3, 31),
                dt.date(2009, 11, 30), dt.date(2010, 3, 31), dt.date(2010, 11, 30),
                dt.date(2011, 3, 31), dt.date(2011, 11, 30), dt.date(2012, 3, 31),
                dt.date(2012, 11, 30), dt.date(2013, 3, 31), dt.date(2013,11, 30)])

    y = np.array([0, -2.15881, -1.18881, -2.91211,  -2.33211,   -5.06131, -4.24131, -6.04321,   -4.56321,   -6.42431,   -5.68431,   -8.83711,   -8.43711,   -11.02821,
                  -10.66821,    -12.90341,  -11.02341,  -13.77671,  -13.27671,  -13.89671,
                  -12.23671,    -13.89411,  -12.61411])

plt.plot(x, y)

I tried the scipy spline but had problem because of my uneven x intervals.


Solution

  • It worked for me!

    You have to convert the dates to numbers and use the scipy.interplolate.spline to make the plot smoother.

    import numpy as np
    from pylab import plt
    import datetime as dt
    from scipy.interpolate import spline
    from matplotlib import dates
    
    x = np.array([dt.date(2000, 11, 30), dt.date(2001, 3, 31), dt.date(2001, 11, 30),
                    dt.date(2002, 3, 31), dt.date(2002, 11, 30), dt.date(2003, 3, 31),
                    dt.date(2003, 11, 30), dt.date(2004, 3, 31), dt.date(2004, 11, 30),
                    dt.date(2005, 3, 31), dt.date(2005, 11, 30), dt.date(2006, 3, 31),
                    dt.date(2006, 11, 30), dt.date(2007, 3, 31), dt.date(2007, 11, 30),
                    dt.date(2008, 3, 31), dt.date(2008, 11, 30), dt.date(2009, 3, 31),
                    dt.date(2009, 11, 30), dt.date(2010, 3, 31), dt.date(2010, 11, 30),
                    dt.date(2011, 3, 31), dt.date(2011, 11, 30)])
    
    y = np.array([0, -2.15881, -1.18881, -2.91211,  -2.33211,   -5.06131, -4.24131, -6.04321,
                   -4.56321,   -6.42431,   -5.68431, -8.83711,   -8.43711,   -11.02821,
                   -10.66821,    -12.90341,  -11.02341,  -13.77671,  -13.27671,  -13.89671,
                   -12.23671,    -13.89411,  -12.61411])
    
    # create an array of numbers for the dates
    x_dates = np.array([dates.date2num(i) for i in x])
    
    plt.figure()
    plt.plot(x, y)
    plt.show()
    
    # create more uniform intervals in x axis and use spline to interpolate data
    x_smooth = np.linspace(x_dates.min(), x_dates.max(), 200)
    y_smooth = spline(x_dates, y, x_smooth)
    
    # creating a new date array from the new date number array
    x_new = np.array([dates.num2date(i) for i in x_smooth])
    
    plt.figure()
    plt.plot(x_new, y_smooth)
    plt.show()
    

    So, the initial figure is:Original Figure

    The new figure is: Interpolated figure

    And superimposing the two figures, we see that the match is pretty good! Superimposing both the plots