Numpy or SciPy Derivative function for non-uniform spacing?

10,494

Solution 1

You can create your own functions using numpy. For the derivatives using forward differences (edit thanks to @EOL, but note that NumPy's diff() is not a differentiate function):

def diff_fwd(x, y): 
    return np.diff(y)/np.diff(x)

"central" differences (it is not necessarily central, depending on your data spacing):

def diff_central(x, y):
    x0 = x[:-2]
    x1 = x[1:-1]
    x2 = x[2:]
    y0 = y[:-2]
    y1 = y[1:-1]
    y2 = y[2:]
    f = (x2 - x1)/(x2 - x0)
    return (1-f)*(y2 - y1)/(x2 - x1) + f*(y1 - y0)/(x1 - x0)

where y contains the function evaluations and x the corresponding "times", such that you can use an arbitrary interval.

Solution 2

This is probably not provided because what you can do instead is take the derivative of your dependent variable (y-values), take the derivative of your independent variable (in your specific case, the timestamps), and then divide the first vector by second.

The definition of the derivative is:

f' = dy / dx

or in your case:

f'(t) = dy / dt

You can use the diff function to calculate each of your numerical dy, the diff function to calculate your numerical dt, and then element divide these arrays to determine f'(t) at each point.

Solution 3

This is a little bit late, but found @dllahr's answer to be very useful and easy to implement with numpy:

>>> import numpy as np
>>> y = [1, 2, 3, 4, 5]
>>> dy = np.gradient(y)
>>> x = [1, 2, 4, 8, 10]
>>> dx = np.gradient(x)
>>> dy/dx
array([1., 0.66666667, 0.33333333, 0.33333333, 0.5])

Solution 4

Scipy's UnivariateSpline.derivative is a simple way to find the derivative of any data set (x-axis must be ordered such that it is increasing).

x  = [1, 3, 8, 10]
y  = [0, 8, 12, 4]
z  = scipy.interpolate.UnivariateSpline.derivative(x,y)
dz = z.derivative(n)

where n is the order of the derivative

ref: https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.interpolate.UnivariateSpline.derivative.html

Note that the default order of UnivariateSpline is 3 and equivalent scipy.interpolate.CubicSpline

Share:
10,494
user3123955
Author by

user3123955

Updated on June 14, 2022

Comments

  • user3123955
    user3123955 almost 2 years

    I was wondering if numpy or scipy had a method in their libraries to find the numerical derivative of a list of values with non-uniform spacing. The idea is to feed in the timestamps that correspond to the values and then for it to use the timestamps to find the numerical derivative.

  • user3123955
    user3123955 over 9 years
    what is a forward and central difference exactly?
  • Saullo G. P. Castro
    Saullo G. P. Castro over 9 years
    @user3123955 check here for example to have an overview about these numerical methods
  • Bruno Feroleto
    Bruno Feroleto about 9 years
    y[1:] - y[:-1] is provided by the more directly legible numpy.diff(y).
  • Saullo G. P. Castro
    Saullo G. P. Castro about 9 years
    @EOL thank you for the hint, I've updated the answer
  • Bruno Feroleto
    Bruno Feroleto about 9 years
    Good. Indeed, diff() does not stand for "differentiate" but for "difference". While you're at it, the central differences are already in NumPy too: numpy.gradient() (docs.scipy.org/doc/numpy/reference/generated/…). :)
  • Pwnna
    Pwnna over 8 years
    How does this formula even work? I thought center differencing is just (y2 - y0) / (x2 - x0)? Am I missing something?
  • Saullo G. P. Castro
    Saullo G. P. Castro over 8 years
    @Pwnna for the central difference you have also to consider the center point (x1, y1)
  • Luke Davis
    Luke Davis about 7 years
    @Pwnna can you tell me where you found that algorithm? Any webpages/textbooks?
  • Jason
    Jason over 6 years
    So this is quite different from its earlier version, innt? For instance I'm using 1.11.3 and its doc suggests that np.gradient(y, x) treats this x as delta x, rather than coordinate of y. That's rather a dangeous trap, if you are not paying attention to the version then the results are totally and silently wrong.
  • Neinstein
    Neinstein over 6 years
    @Jason indeed, I myself fell for this trap. I's only a problem for older releases running code for the new version, as the new version is backwards compatible (afaik). If x was a single number, it'd threat it as delta x.
  • Jason
    Jason over 6 years
    I literally hit the submit button to post a new question (here stackoverflow.com/q/46701906/2005415) 1 second before noticing your reply. I'm not sure should I delete it or keep it? But it's a very nasty bug, I don't know what to do, writing my own implementation?
  • Neinstein
    Neinstein over 6 years
    @Jason I'd leave it, and mention my question in comments as "related". This way the community can make up it's mind and decide whether it's a duplicate. (I don't want to comment this myself, it'd look like rep-hunting...)
  • Pranshu Gupta
    Pranshu Gupta over 5 years
    I don't understand, how is the result calculated, i am not able to arrive at [ 2. , 1.65 , 0.31666667, 4.23333333, 5. ]