Data Visualization and Storytelling
Explore and communicate insights with clear, accessible visuals using Matplotlib, Seaborn, and Plotly.
Content
Time Series Visualizations
Versions:
Watch & Learn
AI-discovered learning video
Sign in to watch the learning video for this topic.
Time Series Visualizations — Tell Better Stories with Time
"Time isn't just another axis — it's a plot with an opinion."
You're coming from a world where you already explored bar charts and scatterplots, and you've prepped your dataset with careful cleaning and feature engineering. Good. That means your timestamps are tidy, missing values handled, and your lag/rolling features are ready to perform. Now we take those cleaned, feature-rich time series and make them sing — or at least not mislead your stakeholders.
Why time series viz is different (and why you should care)
Time series are ordered, autocorrelated, and often seasonal. Unlike a scatterplot, the order matters. Unlike a bar chart, shape over time tells the story: trend, seasonality, cycles, spikes, and anomalies.
Use time series plots to:
- Reveal trends (long-term movement)
- Spot seasonality (regular repeating patterns)
- Highlight anomalies and interventions (single events)
- Validate features created during feature engineering (lags, rolling means)
Imagine showing a CFO a jagged revenue line with no annotation. They'll see noise and panic. Show the smoothed trend plus annotated promotions and suddenly you look like a prophet.
Core plot types and when to use them
1) Line plot — the bread-and-butter
Best for: continuous measurements, daily/monthly series.
Micro explanation: lines connect the order — don't break them if gaps mean missing data; resample instead.
Example (pandas + matplotlib):
import pandas as pd
import matplotlib.pyplot as plt
# df has columns ['date', 'value'] and is cleaned
df['date'] = pd.to_datetime(df['date'])
df = df.set_index('date')
# daily values
df['value'].plot(figsize=(12,4), alpha=0.7)
plt.title('Value over time')
plt.show()
2) Area chart — emphasize volume
Good for cumulative metrics or showing composition over time (stacked area). Use transparency carefully to avoid misinterpretation.
3) Rolling mean / smoothing overlay
Best for: showing trend by removing high-frequency noise.
df['rolling_30'] = df['value'].rolling(window=30, min_periods=1).mean()
df[['value','rolling_30']].plot(figsize=(12,4))
Micro explanation: Pick window sizes so they match the natural period (weekly, monthly) — not because 30 is a round number.
4) Seasonal decomposition
Use statsmodels' seasonal_decompose to split into trend, seasonal, and residual.
from statsmodels.tsa.seasonal import seasonal_decompose
res = seasonal_decompose(df['value'], model='additive', period=365)
res.plot();
This confirms suspected seasonality and justifies engineered seasonal features.
5) Autocorrelation and lag plots
- Autocorrelation (ACF) tells you how many lag features could matter.
- Partial ACF (PACF) helps identify AR order for models.
Example:
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
plot_acf(df['value'].dropna(), lags=50)
plot_pacf(df['value'].dropna(), lags=50)
Micro explanation: Spikes at lag 7 might reveal weekly cycles — a clue to create lag-7 features.
6) Heatmaps (calendar or matrix)
Show seasonal patterns compactly: rows = year, cols = month/day-hour, color = value.
pivot = df['value'].resample('M').mean().reset_index()
pivot['year'] = pivot['date'].dt.year
pivot['month'] = pivot['date'].dt.month
matrix = pivot.pivot('year', 'month', 'value')
import seaborn as sns
sns.heatmap(matrix, cmap='YlGnBu', annot=True)
7) Small multiples (facet grids)
Plot each category/time-slice separately when comparing many similar series — e.g., user cohorts or product lines. This avoids clutter that a single plot would create.
8) Interactive plots (Plotly)
For storytelling, allow zoom + hover to examine spikes.
import plotly.express as px
fig = px.line(df.reset_index(), x='date', y='value')
fig.show()
Practical pattern: From raw data to storytelling plot
- Ensure datetime index and consistent frequency (resample if needed):
- upsample vs downsample: use interpolation for upsample; aggregation for downsample.
- Fill or mark missing data (don't glue over large gaps without noting it).
- Add engineered features where useful: lag_1, lag_7, rolling_mean_7, month, dayofweek.
- Plot raw + smoothed + decomposition to guide the narrative.
- Annotate events: promotions, outages, policy changes.
- Use small multiples or color/grouping for categories.
Example annotation:
plt.figure(figsize=(12,4))
plt.plot(df.index, df['value'], label='value', alpha=0.5)
plt.plot(df.index, df['rolling_30'], label='30-day mean', color='red')
plt.axvline(pd.to_datetime('2023-06-15'), color='black', linestyle='--')
plt.text(pd.to_datetime('2023-06-16'), df['value'].max()*0.9, 'Feature launch')
plt.legend()
Common pitfalls and how to avoid them
- Misleading scales: Avoid forcing a dual y-axis unless you absolutely know your audience and the scales.
- Over-smoothing: Too much smoothing hides real anomalies. Show raw + smoothed.
- Ignoring autocorrelation: If values are correlated across time, standard 'IID' assumptions don't hold — visualize with ACF/PACF.
- Not validating engineered features: Plot lag features against target to ensure predictive signal (use scatterplots/pair plots as you learned earlier).
Quick comparison table
| Plot | Best for | Storytelling tip |
|---|---|---|
| Line | Trends, anomalies | Annotate spikes and label axes clearly |
| Rolling mean | Trend emphasis | Show raw line faintly underneath |
| Decomposition | Understand components | Use to justify seasonal features |
| Heatmap | Seasonal patterns | Use consistent color scale |
| ACF/PACF | Autocorrelation | Use to choose lag features |
Closing: key takeaways (so you don't scroll away forgetting everything)
- Time order matters — preserve it, don't treat timestamps as categories.
- Use resampling, smoothing, decomposition, and ACF/PACF as diagnostic tools to validate your cleaning and feature engineering choices.
- Annotate and narrate: every plot should tell a clear story — trend, why it changed, and what you recommend.
- Build on your previous skills: use scatter/pair plots to inspect lag relationships; use bar/stacked charts to summarize aggregated time slices.
"If your time series plot is noisy and unlabeled, it's a crime against comprehension. Smooth carefully, annotate boldly, and always ask: what story am I trying to tell?"
Tags: time-series visualization, pandas, storytelling
Comments (0)
Please sign in to leave a comment.
No comments yet. Be the first to comment!