Skip to main content

Python NumPy: How to Calculate the Difference Between Neighboring Elements in a NumPy Array

Calculating the difference between consecutive (neighboring) elements in an array is a common operation in data analysis, signal processing, and numerical computing. Whether you need to find rate of change, detect trends, or compute discrete derivatives, NumPy's np.diff() function provides an efficient, vectorized solution that works with both 1D and multi-dimensional arrays.

In this guide, you will learn how to use np.diff() to compute element-wise differences along any axis, handle higher-order differences, and apply this technique to practical scenarios.

How np.diff() Works​

The np.diff() function computes the n-th discrete difference along a given axis. For the default first-order difference, each output element is calculated as:

difference[i] = a[i+1] - a[i]

Since each difference requires two elements, the output array is always one element shorter than the input along the differenced axis.

Syntax​

numpy.diff(a, n=1, axis=-1, prepend=<no value>, append=<no value>)
ParameterDescriptionDefault
aInput array-
nNumber of times to compute differences (order)1
axisAxis along which to compute differences-1 (last axis)
prependValues to prepend before differencingNone
appendValues to append before differencingNone

Returns: An array of n-th differences, with the differenced axis reduced by n elements.

Differences in a 1D Array​

The simplest case: compute the difference between each pair of consecutive elements:

import numpy as np

arr = np.array([1, 12, 3, 14, 5, 16, 7, 18, 9, 110])

result = np.diff(arr)
print(result)

Output:

[ 11  -9  11  -9  11  -9  11  -9 101]

How it works:

12 - 1  =  11
3 - 12 = -9
14 - 3 = 11
5 - 14 = -9
...
110 - 9 = 101

Notice that the input has 10 elements and the output has 9 (one fewer).

Differences in a 2D Array​

For multi-dimensional arrays, the axis parameter controls the direction of differencing.

Along Columns (axis=0): Row-to-Row Differences​

Each element is subtracted from the element directly below it:

import numpy as np

arr = np.array([
[10, 12, 14],
[25, 35, 45],
[12, 18, 20]
])

result = np.diff(arr, axis=0)
print(result)

Output:

[[ 15  23  31]
[-13 -17 -25]]

How it works:

Row 1 - Row 0: [25-10, 35-12, 45-14] = [15, 23, 31]
Row 2 - Row 1: [12-25, 18-35, 20-45] = [-13, -17, -25]

The input has 3 rows; the output has 2.

Along Rows (axis=1) - Column-to-Column Differences​

Each element is subtracted from the element to its right:

import numpy as np

arr = np.array([
[10, 12, 14],
[25, 35, 45],
[12, 18, 20]
])

result = np.diff(arr, axis=1)
print(result)

Output:

[[ 2  2]
[10 10]
[ 6 2]]

How it works:

Row 0: [12-10, 14-12] = [2, 2]
Row 1: [35-25, 45-35] = [10, 10]
Row 2: [18-12, 20-18] = [6, 2]

Notice that the input has 3 columns and the output has 2.

Higher-Order Differences​

Setting n > 1 computes the difference multiple times. The second-order difference is the difference of the differences (analogous to the second derivative):

import numpy as np

arr = np.array([1, 4, 9, 16, 25])

# First-order difference
first = np.diff(arr, n=1)
print("1st order:", first)

# Second-order difference
second = np.diff(arr, n=2)
print("2nd order:", second)

# Third-order difference
third = np.diff(arr, n=3)
print("3rd order:", third)

Output:

1st order: [3 5 7 9]
2nd order: [2 2 2]
3rd order: [0 0]

This is particularly useful for detecting the rate of change:

  • 1st order: The differences are increasing (3, 5, 7, 9) - the sequence is accelerating.
  • 2nd order: Constant differences (2, 2, 2) - the sequence follows a quadratic pattern (these are perfect squares).
  • 3rd order: All zeros - confirms the sequence is exactly quadratic.

Preserving Array Shape With prepend and append​

Since np.diff() reduces the array length, you sometimes need to maintain the original shape. Use prepend or append to pad the array before differencing:

import numpy as np

arr = np.array([10, 20, 35, 50, 80])

# Prepend 0 so the output has the same length as the input
result = np.diff(arr, prepend=0)
print(f"Input length: {len(arr)}")
print(f"Output length: {len(result)}")
print(f"Result: {result}")

Output:

Input length:  5
Output length: 5
Result: [10 10 15 15 30]

The first element of the result is 10 - 0 = 10, and the output has the same length as the input.

When to use prepend vs. append
  • prepend=0: Useful when the first difference should represent "change from zero" (e.g., cumulative data where the starting point is zero).
  • append: Useful when you want to pad at the end to maintain shape for alignment purposes.
# Prepend: first element = arr[0] - 0
np.diff([10, 20, 30], prepend=0) # [10, 10, 10]

# Append: last element = appended_value - arr[-1]
np.diff([10, 20, 30], append=30) # [10, 10, 0]

Practical Examples​

Detecting Price Changes in Stock Data​

import numpy as np

# Daily closing prices
prices = np.array([150.0, 152.5, 148.0, 155.0, 153.5, 160.0])

# Daily price changes
changes = np.diff(prices)
print("Daily changes:", changes)
print(f"Biggest gain: +{changes.max():.2f}")
print(f"Biggest drop: {changes.min():.2f}")

Output:

Daily changes: [ 2.5 -4.5  7.  -1.5  6.5]
Biggest gain: +7.00
Biggest drop: -4.50

Computing Velocity From Position Data​

import numpy as np

# Position measurements at equal time intervals (1 second apart)
positions = np.array([0, 2, 8, 18, 32, 50]) # meters
time_step = 1.0 # seconds

# Velocity = change in position / change in time
velocity = np.diff(positions) / time_step
print("Velocity (m/s):", velocity)

# Acceleration = change in velocity / change in time
acceleration = np.diff(velocity) / time_step
print("Acceleration (m/s²):", acceleration)

Output:

Velocity (m/s): [ 2.  6. 10. 14. 18.]
Acceleration (m/s²): [4. 4. 4. 4.]

Constant acceleration confirms uniform acceleration (like free fall with a known value).

Finding Where Values Change in a Boolean Array​

import numpy as np

# Signal with on/off states
signal = np.array([0, 0, 1, 1, 1, 0, 0, 1, 0])

# Find transitions (non-zero differences indicate state changes)
transitions = np.diff(signal)
change_indices = np.where(transitions != 0)[0]

print("Transitions:", transitions)
print("Changes occur at indices:", change_indices)

Output:

Transitions: [ 0  1  0  0 -1  0  1 -1]
Changes occur at indices: [1 4 6 7]

Common Mistake: Unexpected Axis With 2D Arrays​

By default, np.diff() operates along the last axis (axis=-1). For a 2D array, this means differences along columns (left to right), which might not be what you expect:

import numpy as np

arr = np.array([[1, 5, 10], [2, 8, 20]])

# āŒ Might expect row-to-row differences, but gets column-to-column
result = np.diff(arr) # Default axis=-1 (along columns)
print(result)

Output:

[[ 4  5]
[ 6 12]]

Fix: Explicitly specify axis=0 for row-to-row differences:

import numpy as np

arr = np.array([[1, 5, 10], [2, 8, 20]])

# āœ… Explicit axis for clarity
result = np.diff(arr, axis=0) # Row-to-row
print(result)

Output:

[[ 1  3 10]]
warning

Always specify axis explicitly when working with multi-dimensional arrays. Relying on the default (axis=-1) can lead to subtle bugs if you assume a different direction.

Quick Reference​

OperationCodeInput ShapeOutput Shape
1D differencenp.diff(arr)(n,)(n-1,)
2D along rows (↓)np.diff(arr, axis=0)(m, n)(m-1, n)
2D along columns (→)np.diff(arr, axis=1)(m, n)(m, n-1)
2nd-order differencenp.diff(arr, n=2)(n,)(n-2,)
Preserve lengthnp.diff(arr, prepend=0)(n,)(n,)

Conclusion​

NumPy's np.diff() function is the standard tool for computing differences between neighboring elements in an array. It supports any number of dimensions via the axis parameter, higher-order differences via the n parameter, and shape preservation via prepend and append.

Whether you are analyzing time series data, computing numerical derivatives, or detecting state changes in signals, np.diff() provides a fast, vectorized solution that avoids explicit loops and keeps your code clean and efficient.