Of course! The term "peakdetect" in Python most commonly refers to finding local maxima and minima in a one-dimensional signal or dataset. While there isn't a built-in function in Python's standard library for this, it's a very common task, and several excellent libraries and custom functions exist to solve it.

Here’s a comprehensive guide covering the most popular and effective methods.
What is Peak Detection?
The goal is to find points in a data series that are higher (for maxima) or lower (for minima) than their immediate neighbors.
- Local Maximum (Peak): A point
x[i]is a local maximum ifx[i-1] < x[i]andx[i] > x[i[i+1]. - Local Minimum (Valley/Trough): A point
x[i]is a local minimum ifx[i-1] > x[i]andx[i] < x[i[i+1].
Simple methods can find all these points, but often you only want the "significant" ones. This is where more advanced techniques come in.
Method 1: The SciPy find_peaks Function (Recommended)
This is the standard, most powerful, and recommended way to perform peak detection in scientific Python. It's part of the scipy.signal module and offers a wide range of parameters to fine-tune your search.

Installation
If you don't have SciPy, install it:
pip install scipy numpy matplotlib
Basic Usage
The function scipy.signal.find_peaks() returns the indices of the peaks.
import numpy as np import matplotlib.pyplot as plt from scipy.signal import find_peaks # 1. Create sample data x = np.linspace(0, 10, 200) data = np.sin(x) + 0.5 * np.random.normal(size=200) # Noisy sine wave # 2. Find peaks # find_peaks returns two arrays: # - peaks: indices of the peaks # - properties: a dictionary of properties (e.g., width, prominence) peaks, _ = find_peaks(data) # 3. Find valleys (minima) # A valley is a peak in the inverted data valleys, _ = find_peaks(-data) # 4. Plot the results plt.figure(figsize=(10, 6)) plt.plot(x, data, label='Signal') plt.plot(x[peaks], data[peaks], "x", label='Peaks', color='red', markersize=10) plt.plot(x[valleys], data[valleys], "o", label='Valleys', color='green', markersize=8) plt.legend()"Basic Peak and Valley Detection with SciPy") plt.show()
Advanced Parameters: Finding "Significant" Peaks
The real power of find_peaks is in its parameters to filter out noise and find only the most prominent features.
height: Peaks must be higher than this value.threshold: Vertical distance required to the neighboring samples.distance: Horizontal distance (in samples) required between neighboring peaks.prominence: The vertical distance between a peak and its lowest contour line. This is often the most useful parameter for finding "true" peaks in noisy data.width: Minimum width of peaks (in samples).
Example with Prominence and Distance:

Let's use a more complex signal.
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import find_peaks
# Create a more complex signal
x = np.linspace(0, 50, 500)
data = np.cos(x) + 0.5 * np.cos(10*x) + 0.1 * np.random.normal(size=len(x))
# Find peaks with specific criteria
# - prominence: at least 1.0
# - distance: at least 20 samples apart
peaks, properties = find_peaks(data, prominence=1.0, distance=20)
print(f"Found {len(peaks)} significant peaks.")
# Plot
plt.figure(figsize=(12, 6))
plt.plot(x, data, label='Complex Signal')
plt.plot(x[peaks], data[peaks], "x", label='Significant Peaks', color='red', markersize=12, mew=2)
plt.legend()"Advanced Peak Detection with Prominence and Distance")
plt.show()
# You can inspect the properties of the found peaks
print("\nPeak Properties:")
print(properties['promence']) # Note: the key is 'promence' in the properties dict
Method 2: Custom Peak Detection Function
If you want a lightweight solution without adding a dependency or need to understand the underlying logic, you can write a simple function.
This function will find all local maxima based on a simple comparison.
import numpy as np
import matplotlib.pyplot as plt
def find_peaks_simple(data):
"""
Finds all local maxima in a 1D numpy array.
Returns a list of indices of the peaks.
"""
peaks = []
for i in range(1, len(data) - 1):
if data[i-1] < data[i] and data[i] > data[i+1]:
peaks.append(i)
return peaks
# Create sample data
x = np.linspace(0, 10, 200)
data = np.sin(x) + 0.5 * np.random.normal(size=200)
# Find peaks using the custom function
peak_indices = find_peaks_simple(data)
# Plot
plt.figure(figsize=(10, 6))
plt.plot(x, data, label='Signal')
plt.plot(x[peak_indices], data[peak_indices], "x", label='Peaks (Custom)', color='red', markersize=10)
plt.legend()"Simple Custom Peak Detection")
plt.show()
Limitations of the Simple Method:
- It finds every local maximum, including small ones caused by noise.
- It has no built-in way to set thresholds for height, width, or prominence.
- It can't handle plateaus (e.g.,
[1, 2, 2, 1]) where a peak isn't strictly greater than its neighbors.
Method 3: Using Pandas
If your data is already in a Pandas Series, you can use its methods to find peaks. This is less direct but can be useful within a Pandas-based workflow.
The rolling window is key here. We can compare each point to its neighbors using a window of size 3.
import pandas as pd import numpy as np import matplotlib.pyplot as plt # Create a Pandas Series x = np.linspace(0, 10, 200) data_series = pd.Series(np.sin(x) + 0.5 * np.random.normal(size=200), index=x) # Find peaks: a point is a peak if it's greater than the points before and after it. # We use a rolling window of 3 and check if the current point is the maximum. is_peak = data_series.rolling(window=3, center=True).max() == data_series # Get the index of the peaks peak_indices = data_series[is_peak].index # Plot plt.figure(figsize=(10, 6)) data_series.plot(label='Signal') plt.scatter(peak_indices, data_series.loc[peak_indices], color='red', label='Peaks (Pandas)', zorder=5, marker='x', s=100) plt.legend()"Peak Detection with Pandas") plt.show()
Summary and Comparison
| Method | Pros | Cons | Best For |
|---|---|---|---|
scipy.signal.find_peaks |
Most powerful and flexible. Excellent documentation. Handles noise well with parameters like prominence and width. |
Requires SciPy (a core scientific library). | Most use cases. Signal processing, scientific analysis, data science where you need to find significant features in noisy data. |
| Custom Function | No external dependencies. Good for learning the logic. | Very basic. No built-in filtering for noise. Can be slow for large arrays. | Simple, clean data or for educational purposes. |
| Pandas Rolling | Integrates seamlessly into a Pandas workflow. | Less intuitive than SciPy. Can be less performant than NumPy/SciPy for this specific task. | When your data is already in a Pandas DataFrame/Series and you want to avoid another import. |
Final Recommendation
For any serious data analysis or signal processing task in Python, use scipy.signal.find_peaks. It is the industry standard for a reason. Its parameters give you fine-grained control to separate the signal from the noise and find exactly the peaks you're looking for.
