9

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
  • 2,809
  • 6
  • 20
  • 21

5 Answers5

7

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.

Pwnna
  • 9,178
  • 21
  • 65
  • 91
Saullo G. P. Castro
  • 56,802
  • 26
  • 179
  • 234
6

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])
pingul
  • 3,351
  • 3
  • 25
  • 43
4

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.

dllahr
  • 421
  • 1
  • 4
  • 13
2

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

DivideByZero
  • 131
  • 2
  • 11
1

Since the newest NumPy release (1.13), numpy.gradient has this feature implemented (documentation):

>>> #only numpy 1.13 and above
>>> import numpy as np
>>> y = [1, 3, 4, 6, 11]
>>> x = [0, 1, 5, 10, 11]
>>> np.gradient(y, x)
array([ 2.        ,  1.65      ,  0.31666667,  4.23333333,  5.        ])

Here the values in x mark the x-coordinates of the y-values in y.

Neinstein
  • 958
  • 2
  • 11
  • 31
  • 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. – Jason Oct 12 '17 at 03:12
  • @Jason indeed, I myself [fell for this trap](https://stackoverflow.com/q/45776214/5099168). 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. – Neinstein Oct 12 '17 at 05:15
  • I literally hit the submit button to post a new question (here https://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? – Jason Oct 12 '17 at 05:22
  • @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...) – Neinstein Oct 12 '17 at 21:58
  • I don't understand, how is the result calculated, i am not able to arrive at [ 2. , 1.65 , 0.31666667, 4.23333333, 5. ] – Pranshu Gupta Sep 08 '18 at 09:18