Fourier Transform in Python with scipy.fft

For anyone working with signals, time series, or periodic data in Python, the Fourier Transform is the core tool for frequency analysis. Use numpy.fft or scipy.fft when you need to decompose a signal into its constituent frequencies, analyze spectra, filter noise, or transform between time and frequency domains.

This guide gives you the fastest way to get useful results, covering what matters for students and engineers.

P.S. scroll to the bottom for a complete SciPy beginner’s learning path.

When to Use FFT in Python

Use FFT (Fast Fourier Transform) when you want to:

  • Identify periodicities in data (e.g., frequencies in audio, vibration, financial series).
  • Filter signals (remove noise, isolate components).
  • Analyze spectral properties for engineering, science, or machine learning.
  • Move between time and frequency domains for any 1D or multi-dimensional signal.

Choose numpy.fft for small to moderate signals and learning. Use scipy.fft for more features, speed, and compatibility with real-world (multi-dimensional, real-valued, or large) signals.

Getting Started: FFT Basics

Suppose you have a sampled signal and want to find out what frequencies are present.

import numpy as np
import matplotlib.pyplot as plt

# Create a sample signal: sum of two sine waves
fs = 500  # Sampling rate, Hz
t = np.arange(0, 1, 1/fs)
x = 2*np.sin(2*np.pi*50*t) + 0.5*np.sin(2*np.pi*120*t)

# Compute FFT
X = np.fft.fft(x)
freqs = np.fft.fftfreq(len(x), 1/fs)

# Plot spectrum
plt.plot(freqs[:len(x)//2], np.abs(X[:len(x)//2]) * 2 / len(x))
plt.xlabel('Frequency (Hz)')
plt.ylabel('Amplitude')
plt.title('FFT Spectrum')
plt.show()

This gives you the basic recipe: build your signal, run fft, plot the magnitude spectrum. You see sharp peaks at 50 Hz and 120 Hz.

Key points:

  • Always scale the amplitude by 2/N for one-sided spectrum.
  • Only plot positive frequencies for real signals (first half of freqs and X).
  • Use np.fft.fft for simple cases; switch to scipy.fft.fft for better real/complex handling.

Using scipy.fft for Advanced Features

scipy.fft provides the same interface as numpy.fft, but supports multi-dimensional signals, real FFTs, and better performance on large arrays.

from scipy.fft import fft, fftfreq

X = fft(x)
freqs = fftfreq(len(x), 1/fs)

You can also use rfft and rfftfreq for real-valued input, which is faster and avoids redundant output:

from scipy.fft import rfft, rfftfreq

X = rfft(x)
freqs = rfftfreq(len(x), 1/fs)
plt.plot(freqs, np.abs(X) * 2 / len(x))
plt.show()

Filtering and Signal Processing with FFT

FFT enables quick frequency filtering. For example, to remove high-frequency noise, zero out unwanted frequencies and invert the FFT.

# Simple low-pass filter
X_filtered = X.copy()
X_filtered[freqs > 60] = 0
x_filtered = np.fft.ifft(X_filtered).real

plt.plot(t, x, label='Original')
plt.plot(t, x_filtered, label='Filtered')
plt.legend()
plt.show()

The high-frequency (120 Hz) component disappears, leaving only the 50 Hz wave.

Practical Tips and Troubleshooting

  • Signal length: Pad your signal to the next power of two for speed, if required.
  • Sampling rate: Always keep track of your fs (sampling frequency) for correct frequency axis.
  • Windowing: If your signal is not periodic or is windowed, apply a window function (like np.hanning) before FFT to reduce spectral leakage.
  • DC component: The zero-frequency term in the FFT output is the mean (average) of the signal.
  • Real vs complex: For real signals, prefer rfft; for general use, fft handles any input.

Table: Essential FFT Functions in numpy.fft and scipy.fft

FunctionPurposeNotes
fftFFT for any signalUse with fftfreq
ifftInverse FFTReconstructs time signal from spectrum
rfftFFT for real inputFaster, output is positive freq only
irfftInverse real FFTFor reconstructing real time-domain signal
fftfreqFrequency bins for fftUse with length N, sample spacing 1/fs
rfftfreqFreq bins for real FFTPositive freq bins only

When to Use Which FFT

  • Use np.fft for basic teaching and compatibility.
  • Use scipy.fft for large signals, higher speed, and advanced real/complex support.
  • Use rfft and irfft when input data is known to be real-valued (audio, sensor, etc).
  • Use multi-dimensional fft2, fftn, etc., for images and multidimensional arrays.

Skimmable Example: FFT of a Real Signal

from scipy.fft import rfft, rfftfreq, irfft

fs = 1000
t = np.linspace(0, 1, fs, endpoint=False)
signal = np.sin(2*np.pi*100*t) + 0.2*np.random.randn(fs)

# FFT
freqs = rfftfreq(len(signal), 1/fs)
spectrum = rfft(signal)

# Zero out frequencies above 150 Hz
spectrum[freqs > 150] = 0

# Inverse FFT
filtered = irfft(spectrum)

plt.plot(t, signal, alpha=0.7, label='Original')
plt.plot(t, filtered, label='Filtered')
plt.legend()
plt.show()

Summary

Use numpy.fft or scipy.fft for frequency analysis, filtering, and spectrum computation in Python. Start with rfft and rfftfreq for most real-world signals, and remember to scale and interpret your spectrum correctly. For multidimensional or large-scale problems, scipy.fft is the tool of choice.

Ninad Pathak
Ninad Pathak

Ninad is a Python and PHP developer turned writer out of passion. Over the last 6+ years, he has written for brands including DigitalOcean, DreamHost, Hostinger, and many others. When not working, you'll find him tinkering with open-source projects, vibe coding, or on a mountain trail, completely disconnected from tech.

Articles: 46