The key phrase from the docs is:

The gradient is computed using second order accurate central differences in the interior points ...

This means that each group of three contiguous points is adjusted to a parabola (2nd order polynomial) and its slope at the location of the central point is used as the gradient.

For evenly spaced data (with a spacing of 1) the formula is very simple:

g(i) = 0.5 f(i+1) - 0.5 f(i-1)

Then comes the problematic part:

... and either first or second order accurate one-sides (forward or backwards) differences at the boundaries.

There is neither f(i+1) at the right boundary nor f(i-1) at the left boundary.

So you can use a simple 1st order approximation

g(0) = f(1) - f(0)
g(n) = f(n) - f(n-1)

or a more complex 2nd order approximation

g(0) = -1.5 f(0) + 2 f(1) - 0.5 f(2)
g(n) = 0.5 f(n-2) - 2 f(n-1) + 1.5 f(n)

The effect can be seen in this example, copied from the docs:

>>> x = np.array([0, 1, 2, 3, 4])
>>> f = x**2
>>> np.gradient(f, edge_order=1)
array([1., 2., 4., 6., 7.])
>>> np.gradient(f, edge_order=2)
array([0., 2., 4., 6., 8.])

The derivation of the coefficient values can be found here.

Answer from aerobiomat on Stack Overflow
Discussions

DOC: suggestion, beware of `np.gradient( edge_order=2 )`
Beware of np.gradient( edge_order=2 ); it can overshoot on noisy data, or on non-uniformly-spaced grids. More on github.com
🌐 github.com
6
January 16, 2025
Improving numpy.gradient to be second order accurate over the full domain
Currently gradient uses a second order accurate central finite difference for interior elements, and a first order accurate forward (backwards) finite difference for the first (last) element. This ... More on github.com
🌐 github.com
8
August 12, 2013
🌐
NumPy
numpy.org › doc › 2.1 › reference › generated › numpy.gradient.html
numpy.gradient — NumPy v2.1 Manual
>>> x = np.array([0, 1, 2, 3, 4]) >>> f = x**2 >>> np.gradient(f, edge_order=1) array([1., 2., 4., 6., 7.]) >>> np.gradient(f, edge_order=2) array([0., 2., 4., 6., 8.]) The axis keyword can be used to specify a subset of axes of which the gradient is calculated ·
🌐
GitHub
github.com › numpy › numpy › issues › 28166
DOC: suggestion, beware of `np.gradient( edge_order=2 )` · Issue #28166 · numpy/numpy
January 16, 2025 - """ show how np.gradient( edge_order=2 ) can overshoot: slopes 10, 1 -> -3.5 """ import numpy as np print( f"{np.__version__ = } \n" ) for a in [0, 5, 10]: for edge_order in [1, 2]: x = np.array([ 0, 1, 2 ]) y = np.array([ 0, a, a + 1 ]) # slope a, then 1 g = np.gradient( y, x, edge_order=edge_order ) ...
Author   denis-bz
🌐
NumPy
numpy.org › doc › stable › reference › generated › numpy.gradient.html
numpy.gradient — NumPy v2.4 Manual
>>> x = np.array([0, 1, 2, 3, 4]) >>> f = x**2 >>> np.gradient(f, edge_order=1) array([1., 2., 4., 6., 7.]) >>> np.gradient(f, edge_order=2) array([0., 2., 4., 6., 8.]) The axis keyword can be used to specify a subset of axes of which the gradient is calculated ·
🌐
NumPy
numpy.org › devdocs › reference › generated › numpy.gradient.html
numpy.gradient — NumPy v2.5.dev0 Manual
>>> x = np.array([0, 1, 2, 3, 4]) >>> f = x**2 >>> np.gradient(f, edge_order=1) array([1., 2., 4., 6., 7.]) >>> np.gradient(f, edge_order=2) array([0., 2., 4., 6., 8.]) The axis keyword can be used to specify a subset of axes of which the gradient is calculated ·
🌐
TutorialsPoint
tutorialspoint.com › return-the-gradient-of-an-n-dimensional-array-and-specify-edge-order-in-python
Return the gradient of an N-dimensional array over given axis in Python
February 28, 2022 - The gradient calculation uses different methods for different positions: Interior points − Second-order central differences: (f[i+1] - f[i-1]) / 2 · Boundary points − Forward or backward differences based on edge_order parameter · Return value − Array(s) with the same shape as input · np....
Find elsewhere
🌐
NumPy
numpy.org › doc › 1.25 › reference › generated › numpy.gradient.html
numpy.gradient — NumPy v1.25 Manual
>>> x = np.array([0, 1, 2, 3, 4]) >>> f = x**2 >>> np.gradient(f, edge_order=1) array([1., 2., 4., 6., 7.]) >>> np.gradient(f, edge_order=2) array([0., 2., 4., 6., 8.]) The axis keyword can be used to specify a subset of axes of which the gradient is calculated ·
Top answer
1 of 6
8

I'll second @jrennie's first sentence - it can all depend. The numpy.gradient function requires that the data be evenly spaced (although allows for different distances in each direction if multi-dimensional). If your data does not adhere to this, than numpy.gradient isn't going to be much use. Experimental data may have (OK, will have) noise on it, in addition to not necessarily being all evenly spaced. In this case it might be better to use one of the scipy.interpolate spline functions (or objects). These can take unevenly spaced data, allow for smoothing, and can return derivatives up to k-1 where k is the order of the spline fit requested. The default value for k is 3, so a second derivative is just fine. Example:

spl = scipy.interpolate.splrep(x,y,k=3) # no smoothing, 3rd order spline
ddy = scipy.interpolate.splev(x,spl,der=2) # use those knots to get second derivative 

The object oriented splines like scipy.interpolate.UnivariateSpline have methods for the derivatives. Note that the derivative methods are implemented in Scipy 0.13 and are not present in 0.12.

Note that, as pointed out by @JosephCottham in comments in 2018, this answer (good for Numpy 1.08 at least), is no longer applicable since (at least) Numpy 1.14. Check your version number and the available options for the call.

2 of 6
6

There's no universal right answer for numerical gradient calculation. Before you can calculate the gradient about sample data, you have to make some assumption about the underlying function that generated that data. You can technically use np.diff for gradient calculation. Using np.gradient is a reasonable approach. I don't see anything fundamentally wrong with what you are doing---it's one particular approximation of the 2nd derivative of a 1-D function.

🌐
SciPy
docs.scipy.org › doc › numpy-1.9.3 › reference › generated › numpy.gradient.html
numpy.gradient — NumPy v1.9 Manual
>>> x = np.array([0, 1, 2, 3, 4]) >>> dx = np.gradient(x) >>> y = x**2 >>> np.gradient(y, dx, edge_order=2) array([-0., 2., 4., 6., 8.])
🌐
Finxter
blog.finxter.com › home › learn python blog › np.gradient() — a simple illustrated guide
np.gradient() - A Simple Illustrated Guide - Be on the Right Side of Change
June 24, 2022 - Just to refresh your memory, here is the argument table of numpy.gradient(): We can set the argument edge_order to be 1 or 2. Its default value is 1. First, our previous basic example uses its default value, 1. import numpy as np # edge_order ...
🌐
SciPy
docs.scipy.org › doc › numpy-1.10.1 › reference › generated › numpy.gradient.html
numpy.gradient — NumPy v1.10 Manual
For two dimensional arrays, the return will be two arrays ordered by axis. In this example the first array stands for the gradient in rows and the second one in columns direction: >>> np.gradient(np.array([[1, 2, 6], [3, 4, 5]], dtype=np.float)) [array([[ 2., 2., -1.], [ 2., 2., -1.]]), array([[ 1. , 2.5, 4. ], [ 1. , 1. , 1. ]])] >>> x = np.array([0, 1, 2, 3, 4]) >>> dx = np.gradient(x) >>> y = x**2 >>> np.gradient(y, dx, edge_order=2) array([-0., 2., 4., 6., 8.])
🌐
Finxter
blog.finxter.com › 5-best-ways-to-return-the-gradient-of-an-n-dimensional-array-and-specify-edge-order-in-python
5 Best Ways to Return the Gradient of an N Dimensional Array and Specify Edge Order in Python – Be on the Right Side of Change
This method involves calculating the gradient of an array utilizing NumPy’s built-in gradient function, which returns the gradient along each dimension. By default, this function uses an edge order of 1, which means it employs a first-order difference at the boundaries. ... import numpy as ...
🌐
MindSpore
mindspore.cn › docs › en › r2.0 › api_python › numpy › mindspore.numpy.gradient.html
mindspore.numpy.gradient | MindSpore 2.0 documentation | MindSpore
The default (axis = None) is to calculate the gradient for all the axes of the input tensor. axis may be negative, in which case it counts from the last to the first axis. edge_order (int) – Gradient is calculated using N-th order accurate differences at the boundaries.
🌐
MindSpore
mindspore.cn › docs › en › r1.7 › api_python › numpy › mindspore.numpy.gradient.html
mindspore.numpy.gradient | MindSpore 1.7 documentation | MindSpore
The default (axis = None) is to calculate the gradient for all the axes of the input tensor. axis may be negative, in which case it counts from the last to the first axis. edge_order (int) – Gradient is calculated using N-th order accurate differences at the boundaries.
🌐
NumPy
numpy.org › doc › 2.0 › reference › generated › numpy.gradient.html
numpy.gradient — NumPy v2.0 Manual
>>> x = np.array([0, 1, 2, 3, 4]) >>> f = x**2 >>> np.gradient(f, edge_order=1) array([1., 2., 4., 6., 7.]) >>> np.gradient(f, edge_order=2) array([0., 2., 4., 6., 8.]) The axis keyword can be used to specify a subset of axes of which the gradient is calculated ·
🌐
NumPy
numpy.org › doc › 2.3 › reference › generated › numpy.gradient.html
numpy.gradient — NumPy v2.3 Manual
>>> x = np.array([0, 1, 2, 3, 4]) >>> f = x**2 >>> np.gradient(f, edge_order=1) array([1., 2., 4., 6., 7.]) >>> np.gradient(f, edge_order=2) array([0., 2., 4., 6., 8.]) The axis keyword can be used to specify a subset of axes of which the gradient is calculated ·
🌐
GitHub
github.com › numpy › numpy › issues › 3603
Improving numpy.gradient to be second order accurate over the full domain · Issue #3603 · numpy/numpy
August 12, 2013 - def gradient_second_order(y, dx=1): """Returns second order accurate derivative of y using constant step size dx.""" assert np.isscalar(dx), "dx must be a constant." dy = np.zeros_like(y) # Second order forward difference for first element dy[0] = -(3*y[0] - 4*y[1] + y[2]) / (2*dx) # Central difference interior elements dy[1:-1] = (y[2:] - y[0:-2])/(2*dx) # Backwards difference final element dy[-1] = (3*y[-1] - 4*y[-2] + y[-3]) / (2*dx) return dy ·
Author   danieljfarrell
🌐
TutorialKart
tutorialkart.com › numpy › numpy-gradient
NumPy gradient() - Gradient of N-D Array
February 2, 2025 - import numpy as np # Define a 2D ... Gradient along y-axis: [[1. 2. 4.] [1. 2. 4.] [1. 2. 4.]] We use edge_order=2 for higher accuracy at the boundaries....