HOWTO · Python
How to Find Peaks in Python
Learn how to find local maxima in Python with NumPy, scipy.signal.find_peaks(), scipy.signal.argrelextrema(), and detecta.detect_peaks(), with examples and guidance for choosing a method.
On this page
A local maximum is a sample greater than nearby samples; it need not be the largest value in the whole series. For a one-dimensional sequence, compare each interior value with its neighbors for a simple result, or use scipy.signal.find_peaks() when you need to filter candidates. These functions return zero-based indices into the original data, so use those indices to retrieve peak values.
Use NumPy to find simple local maxima
This compact example uses a one-dimensional array and reports each detected index with its value.
import numpy as np
data = np.array([1, 3, 7, 1, 2, 6, 0, 5, 0, 4])
local_maxima = (data[1:-1] > data[:-2]) & (data[1:-1] > data[2:])
indices = np.flatnonzero(local_maxima) + 1
print("indices:", indices.tolist())
print("values:", data[indices].tolist())
indices: [2, 5, 7]
values: [7, 6, 5]
The two comparisons require a sample to be strictly greater than both immediate neighbors. The slice compares only interior samples, so the first and last elements are not candidates; equal-valued plateaus are also excluded. The index offset maps the shorter comparison array back to positions in data. This NumPy approach is useful when that precise rule fits your data. For this input, the detected indices are [2, 5, 7] and the corresponding values are [7, 6, 5].
Use scipy.signal.find_peaks() to filter peaks
For a general one-dimensional peak search, SciPy’s scipy.signal.find_peaks() returns indices of local maxima and can apply optional conditions. The following example selects peaks with height at least 3 and prints both their indices and values:
import numpy as np
from scipy.signal import find_peaks
data = np.array([1, 3, 7, 1, 2, 6, 0, 5, 0, 4])
indices, properties = find_peaks(data, height=3, distance=2, prominence=1)
print("indices:", indices.tolist())
print("values:", data[indices].tolist())
indices: [2, 5, 7]
values: [7, 6, 5]
height filters by the peak’s value, distance enforces spacing between retained peaks in samples, and prominence measures how much a peak stands out from its surroundings. distance affects which peaks are retained; it is not returned as a property. Other optional conditions include width and threshold. SciPy returns indices plus a properties dictionary containing properties produced for applicable requested conditions. For this input and these arguments, the returned indices are [2, 5, 7], with values [7, 6, 5]. Choose conditions that describe the signal rather than assuming every local maximum is meaningful.
Use scipy.signal.argrelextrema() to find relative extrema
Use scipy.signal.argrelextrema() when you want to compare samples across a specified neighborhood. Pass a comparator such as np.greater to find maxima and set order to the number of samples on each side included in the comparison. Its result is a tuple of index arrays, one for each input dimension; for a one-dimensional array, access the indices with [0].
import numpy as np
from scipy.signal import argrelextrema
data = np.array([1, 3, 7, 1, 2, 6, 0, 5, 0, 4])
indices = argrelextrema(data, np.greater, order=1)[0]
print("indices:", indices.tolist())
print("values:", data[indices].tolist())
indices: [2, 5, 7]
values: [7, 6, 5]
With order=1, this compares each candidate with one sample on either side. A larger order uses a wider neighborhood and can return a different set of relative extrema. For this input with order=1, the returned indices are [2, 5, 7] and their values are [7, 6, 5].
Use detecta.detect_peaks() as an alternative
detecta.detect_peaks() is a third-party alternative for a one-dimensional sequence. Install the dependency in your project environment with python -m pip install detecta, then pass the sample data to detect_peaks():
data = [1, 3, 7, 1, 2, 6, 0, 5, 0, 4]
try:
from detecta import detect_peaks
except ImportError:
print("Install detecta with: python -m pip install detecta")
else:
indices = detect_peaks(data)
values = [data[index] for index in indices]
print("indices:", list(indices))
print("values:", values)
For the sample sequence, the expected zero-based peak indices are [2, 5, 7], corresponding to values [7, 6, 5]. The supplied runtime evidence confirms only the missing-dependency message, so this detecta result is an expected comparison rather than an observed runtime output. Keep the import guard: when detecta is unavailable, it prints the installation command instead of attempting detection.
Choose a peak detection method
Use the NumPy comparison when immediate-neighbor strict maxima are the complete rule you need and you want to see the logic directly. Choose scipy.signal.find_peaks() when filtering by conditions such as height, spacing, prominence, or width matters. Use scipy.signal.argrelextrema() when the comparison neighborhood and comparator are central to your definition of an extremum. Consider detecta.detect_peaks() if its third-party API fits your project and you are willing to add that dependency.
All returned positions are zero-based indices into the input sequence. Compare the method’s definition with your data before interpreting the result: endpoint handling, plateaus, and filtering conditions differ. The examples above cover local maxima in one-dimensional numeric data; multidimensional peak detection requires a method designed for that data shape.