How can I calculate a rolling / moving average using Python NumPy / SciPy?
ML System Design practice on Codemia
Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.
Introduction
A rolling or moving average smooths a sequence by replacing each position with the average of values in a nearby window. In Python, the most common NumPy solutions use cumulative sums or convolution, while SciPy offers convenient filters for the same idea. The best method depends on whether you care most about speed, edge handling, or keeping the output aligned with the original series length.
Use np.convolve for a Simple Moving Average
For many cases, convolution is the cleanest approach. A simple moving average is just convolution with a flat kernel whose values sum to 1.
With mode="valid", only positions where the full window fits are returned. That is why the output is shorter than the input.
This is often the best answer when someone wants a concise moving average over a one-dimensional array and is comfortable with a shorter result.
Use np.cumsum When You Want Efficient Sliding Sums
A cumulative-sum approach is also common and can be very efficient for large arrays.
The idea is simple: once you know cumulative sums, the sum of any fixed-width window can be obtained by subtraction. That avoids recomputing each window sum from scratch.
This method is especially useful when you want to understand the mechanics of the rolling average rather than only call a black-box function.
Keep the Output Length with Padding or same Mode
Sometimes you want one result per input element. In that case, you need to decide how to handle the edges where a full centered window is not available.
A quick approach is mode="same".
This keeps the output length equal to the input length, but the boundary behavior is determined by how convolution pads the missing values. That may or may not match the semantics you want.
So the real question is not only “how do I compute the average”. It is “what should happen at the edges”.
SciPy Gives You More Control Over Edge Handling
SciPy’s filtering utilities are convenient when you want smoothing plus explicit control over boundary rules.
The mode argument controls what values are assumed beyond the boundaries. For example, nearest extends the edge value outward. Other modes give different behavior.
This is often more expressive than trying to reverse-engineer what a specific convolution padding choice means for the first and last few elements.
Choose the Window Based on the Signal
The implementation is only part of the problem. The window size determines how aggressively you smooth the series.
- a small window preserves short-term variation,
- a large window emphasizes long-term trends,
- and a centered window behaves differently from a trailing window used in time-series reporting.
If the rolling average is used for analytics dashboards or finance-style reporting, make sure the window definition matches the business meaning. A mathematically correct average with the wrong window semantics is still the wrong answer.
Missing Values Need a Policy
Pure NumPy approaches will happily propagate NaN values unless you handle them explicitly. If the data can contain missing entries, decide whether you want to ignore them, fill them, or let them invalidate each window.
That decision changes the implementation. There is no single universally correct rule.
Common Pitfalls
- Using
mode="same"without understanding the implied edge behavior. - Expecting a centered moving average when the code actually computes a trailing one.
- Forgetting that
validmode shortens the output array. - Choosing a window size based only on aesthetics rather than the meaning of the signal.
- Ignoring
NaNhandling when the input data is incomplete.
Summary
- In NumPy, moving averages are commonly computed with convolution or cumulative sums.
- '
np.convolveis concise, whilenp.cumsumexposes the sliding-sum logic directly.' - SciPy filters such as
uniform_filter1dare useful when edge handling matters. - Output alignment and boundary behavior are part of the problem, not an afterthought.
- The right window size depends on the analysis goal, not only on implementation convenience.
Related reading
- How can I calculate the point between two overlapping linear datasets?
- How can I check for average concurrent events in a SQL table based on the date, time and duration of the events?
- How can I check whether a numpy array is empty or not?
- How can I construct a tree using d3 and its force layout?
- How can I call a function within a class?
- How can I call a shell script from Python code?
- How can I control the number of output files written from Spark DataFrame?
- How can I convert TFRecords into numpy arrays?
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
ML System Design practice on Codemia
Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.