Search code examples
pythongraphmatplotlibpolynomial-math

identify graph uptrend or downtrend


I am attempting to read in data and plot them on to a graph using python (standard line graph). Can someone please advise on how I can classify whether certain points in a graph are uptrends or downtrends programmatically? Which would be the most optimal way to achieve this? Surely this is a solved problem and a mathematical equation exists to identify this?

here is some sample data with some up trends and downtrends

x = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30]
y = [2,5,7,9,10,13,16,18,21,22,21,20,19,18,17,14,10,9,7,5,7,9,10,12,13,15,16,17,22,27]

thanks in advance


Solution

  • A simple way would be to look at the 'rate in change of y with respect to x', known as the derivative. This usually works better with continuous (smooth) functions, and so you could implement it with your data by interpolating your data with an n-th order polynomial as already suggested. A simple implementation would look something like this:

    import numpy as np
    import matplotlib.pyplot as plt
    from scipy.interpolate import interp1d
    from scipy.misc import derivative
    
    x = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,\
                  16,17,18,19,20,21,22,23,24,25,26,27,28,29,30])
    y = np.array([2,5,7,9,10,13,16,18,21,22,21,20,19,18,\
                  17,14,10,9,7,5,7,9,10,12,13,15,16,17,22,27])
    
    # Simple interpolation of x and y    
    f = interp1d(x, y)
    x_fake = np.arange(1.1, 30, 0.1)
    
    # derivative of y with respect to x
    df_dx = derivative(f, x_fake, dx=1e-6)
    
    # Plot
    fig = plt.figure()
    ax1 = fig.add_subplot(211)
    ax2 = fig.add_subplot(212)
    
    ax1.errorbar(x, y, fmt="o", color="blue", label='Input data')
    ax1.errorbar(x_fake, f(x_fake), label="Interpolated data", lw=2)
    ax1.set_xlabel("x")
    ax1.set_ylabel("y")
    
    ax2.errorbar(x_fake, df_dx, lw=2)
    ax2.errorbar(x_fake, np.array([0 for i in x_fake]), ls="--", lw=2)
    ax2.set_xlabel("x")
    ax2.set_ylabel("dy/dx")
    
    leg = ax1.legend(loc=2, numpoints=1,scatterpoints=1)
    leg.draw_frame(False)
    

    Differential plot of y

    You see that when the plot transitions from an 'upwards trend' (positive gradient) to a 'downwards trend' (negative gradient) the derivative (dy/dx) goes from positive to negative. The transition of this happens at dy/dx = 0, which is shown by the green dashed line. For the scipy routines you can look at:

    http://docs.scipy.org/doc/scipy/reference/generated/scipy.misc.derivative.html

    http://docs.scipy.org/doc/scipy/reference/tutorial/interpolate.html

    NumPy's diff/gradient should also work, and not require the interpolation, but I showed the above so you could get the idea. For a complete mathemetical description of differentiation/calculus, look at wikipedia.