How to Use Kalman Filters for Time Series Analysis in Python

How to Use Kalman Filters for Time Series Analysis in Python
Image by Author | Canva

According to Wikipedia, Kalman filters, which are also known as linear quadratic estimation, are a powerful algorithm that makes use of a series of measurements this is observed over time, and this includes statistical noise and other inaccuracies. With the goal of producing estimates of unknown variables that tend to be more accurate than those based on a single measurement, it does this by estimating a joint probability distribution over the variables for each step.

How to Use Kalman Filters for Time Series Analysis in Python
The Kalman filter | Image source: Wikipedia

The Kalman filter records the system’s estimated state and the estimate’s variance or uncertainty. To understand how it works, let’s break this down in the next section of this article.

How the Kalman Filter Works

Now that we’ve reviewed the key parts, let’s examine how the Kalman filter actually works. It follows a repeated two-step process: predict and update. This cycle runs repeatedly, helping the filter stay on track as new data arrives.

The Predict-Update Cycle

This predict-update loop allows the filter to adjust itself over time and improve its estimation of the real state, even if the observations are noisy.

Predict Update
In this step, the Kalman filter uses the last known state to guess about the current state and predict how uncertain this guess might be. When a new observation (measurement) arrives, the filter compares it with the prediction. If there’s a difference, the filter updates its guess by combining the prediction and the observation, taking their uncertainty into account.

1. State Equation (Prediction Step)
This tells the filter how to move from one state to the next.

Xt = A · xt-1 + B · ut + wt

  • Xt​: current state
  • A: how the system changes over time
  • B⋅ut​​: any external influence (optional)
  • wt​​: process noise (random changes we can’t control)

This formula shows how the filter predicts what the state will be before seeing the new measurement.

2. Observation Equation (Update Step)
This connects the actual measurement to the state.

zt = H · xt + vt

  • zt​: what we observe (our noisy measurement)
  • H: how the state maps to what we can measure
  • vt​: measurement noise

This equation helps the filter determine how close each prediction is to the new measurement and how much to trust each one.

3. How It Handles Noise
One last thing you need to know about the Kalman filter is how it handles noise, either process noise (randomness in how the system behaves) or measurement noise (this is about randomness in what you observe).

It does a good job calculating how uncertain the prediction and the measurement are because, by default, it assumes no data is perfect. Then, it decides how much to trust each one when making an update. So, it’s practical in the sense that if the prediction is uncertain, it leans more on the measurement.

Using Kalman Filters for Time Series Analysis in Python

Let’s get practical. In this section, we will look at examples of how you can use the Kalman filter to analyse time series data in Python. Time series data is basically a set of values recorded over time. A good example of data like this is the rising and falling of temperature hourly or the prices on the stock market changing every minute, hour, and day.

As a result of this, time series analysis is the set of processes involved in understanding and making sense of this kind of data.

Setting Up the Environment

Before we begin, let’s make sure we have everything we need. You can install the necessary libraries using pip. Open your terminal or command prompt and run:

pip install numpy pandas matplotlib pykalman

We installed these libraries because numpy helps with math and arrays, pandas helps to handle time series data, pykalman makes it easy to use Kalman filters, and matplotlib helps to plot and visualize the data

Example: Smoothing Noisy Data

The idea here is to track the position of a car driving in a straight line, but the GPS readings are noisy. We will use a Kalman filter to get a better estimate of the car’s true position. To do this, we will create mockup data that simulates a moving object, but with some noise to it, then proceed to use the Kalman filter to smooth it out.

1. Import Necessary Libraries

import numpy as np
import matplotlib.pyplot as plt
from pykalman import KalmanFilter
  • numpy helps with numerical calculations and creating arrays
  • matplotlib.pyplot is used for plotting charts
  • pykalman.KalmanFilter gives us tools to apply the Kalman filter in Python

2. Simulate True Position

np.random.seed(1)
n_timesteps = 50
true_position = np.linspace(0, 100, n_timesteps)
  • np.random.seed(1) makes sure we get the same random values every time we run the code (for consistency)
  • n_timesteps = 50 means we are simulating 50 points in time
  • np.linspace(0, 100, n_timesteps) creates 50 evenly spaced numbers from 0 to 100. This represents a smooth, straight-line movement—like a car driving steadily

3. Add Noise to Simulate Measurement

observed_position = true_position + np.random.normal(0, 10, size=n_timesteps)
  • This line simulates noisy data, like a GPS tracker that gives readings with some error
  • np.random.normal(0, 10, size=n_timesteps) adds random noise with a mean of 0 and a standard deviation of 10
  • So now, observed_position is what a sensor might report, with the true value plus some noise

4. Set Up the Kalman Filter

kf = KalmanFilter(initial_state_mean=0, n_dim_obs=1)
kf = kf.em(observed_position, n_iter=10)
smoothed_state, _ = kf.smooth(observed_position)
  • KalmanFilter(initial_state_mean=0, n_dim_obs=1) sets up the filter. We’re saying:
    • The initial guess for the position is 0
    • We have one observation per time step (1D data)
  • kf.em(observed_position, n_iter=10) lets the Kalman filter learn the best settings (like how much noise to expect) using the Expectation-Maximization (EM) algorithm. It runs for 10 iterations to optimize.
  • kf.smooth(observed_position) applies the Kalman filter to smooth the noisy data. It returns an improved estimate of the position at each step

5. Plot the Results

plt.figure(figsize=(10, 5))
plt.plot(true_position, label='True Position')
plt.plot(observed_position, label='Noisy Observation', linestyle='dotted')
plt.plot(smoothed_state, label='Kalman Filter Output')
plt.legend()
plt.title("Kalman Filter Smoothing Example")
plt.xlabel("Time")
plt.ylabel("Position")
plt.show()
  • This block draws the chart so we can see what’s happening
  • true_position is the actual clean movement
  • observed_position is the noisy version
  • smoothed_state is the cleaned-up data from the Kalman filter
  • The chart helps you visually compare how the filter improves the noisy measurements

Here is what the chart looks like:

Kalman filter smoothing example
Kalman filter smoothing example

Example: Apple Stock Prices

From the soothing example above, we can now proceed to work on real-world data instead of mock-up data. We will use the historical stock price data of Apple Inc. AAPL, which can be found on Yahoo Finance.

Apple Inc Stock Prices
Apple Inc Stock Prices | Image Credit

We can also access this data by installing the yfinance library using pip.

pip install yfinance

Let’s load the data and apply the Kalman filter. We’ll use the daily closing prices of Apple Inc. (AAPL) stock.

# importing necessary libraries
import yfinance as yf
import pandas as pd
from pykalman import KalmanFilter
import matplotlib.pyplot as plt

# Download stock data - From January 1, 2024 to May 10, 2025
# Note: Adjust the date range as needed
data = yf.download("AAPL", start="2024-01-01", end="2025-05-10")
prices = data['Close'].values

# Apply Kalman filter
kf = KalmanFilter(initial_state_mean=prices[0], n_dim_obs=1)
kf = kf.em(prices, n_iter=5)
filtered_state, _ = kf.smooth(prices)

# Plot results
plt.figure(figsize=(12, 6))
plt.plot(prices, label="Original Prices", linestyle='dotted')
plt.plot(filtered_state, label="Kalman Filtered Prices", color='orange')
plt.title("Apple Stock Price - Kalman Filter Smoothing")
plt.xlabel("Time")
plt.ylabel("Price (USD)")
plt.legend()
plt.grid(True)

Here is what the chart looks like:

Apple Stock Price
Apple Stock Price

The chart above compares the original Apple stock closing prices with the smoothed prices generated using the Kalman Filter.

  • The blue dotted line represents the original daily closing prices of Apple stock. As expected with real-world financial data, this line is quite jagged, showing many short-term ups and downs due to market noise and volatility.
  • The orange line is the Kalman filtered version of the price data. This line is smoother and less reactive to short-term fluctuations, giving us a clearer view of the underlying trend.

The Kalman Filter tries to separate the actual signal (the general price movement) from the noise (the random short-term jumps). As a result, we can better observe the bigger picture of Apple’s stock performance over the selected time period.

For more context:

  • There’s a noticeable price jump around the 100-day mark. The Kalman filter doesn’t just react to this spike blindly—it smooths it out based on its estimation of the underlying trend.
  • In the last quarter of the data (around days 270 to 330), when prices steeply drop, the filter still follows the overall downward trend but in a more stable, less erratic way than the original data.

Wrapping Up

Kalman Filters are wonderful for smoothing and estimating trends in noisy time series data. But they do have some limitations. They assume everything is linear and the noise follows a normal (Gaussian) distribution, which is not always true in real-world data.

If your data is more complex or non-linear, consider alternatives like particle filters (which are good for non-linear and non-Gaussian systems) or LSTM models, which can learn patterns in time series data without those strict assumptions.

Leave a Reply

Your email address will not be published. Required fields are marked *