8000 Merge pull request #18733 from ecotner/topic/time-series-histogram-ex… · matplotlib/matplotlib@2b055a0 · GitHub
[go: up one dir, main page]

Skip to content

Commit 2b055a0

Browse files
authored
Merge pull request #18733 from ecotner/topic/time-series-histogram-example
Time series histogram plot example
2 parents 0163d0d + ea26862 commit 2b055a0

File tree

1 file changed

+96
-0
lines changed

1 file changed

+96
-0
lines changed
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
"""
2+
=====================
3+
Time Series Histogram
4+
=====================
5+
6+
This example demonstrates how to efficiently visualize large numbers of time
7+
series in a way that could potentially reveal hidden substructure and patterns
8+
that are not immediately obvious, and display them in a visually appealing way.
9+
10+
In this example, we generate multiple sinusoidal "signal" series that are
11+
buried under a larger number of random walk "noise/background" series. For an
12+
unbiased Gaussian random walk with standard deviation of σ, the RMS deviation
13+
from the origin after n steps is σ*sqrt(n). So in order to keep the sinusoids
14+
visible on the same scale as the random walks, we scale the amplitude by the
15+
random walk RMS. In addition, we also introduce a small random offset ``phi``
16+
to shift the sines left/right, and some additive random noise to shift
17+
individual data points up/down to make the signal a bit more "realistic" (you
18+
wouldn't expect a perfect sine wave to appear in your data).
19+
20+
The first plot shows the typical way of visualizing multiple time series by
21+
overlaying them on top of each other with ``plt.plot`` and a small value of
22+
``alpha``. The second and third plots show how to reinterpret the data as a 2d
23+
histogram, with optional interpolation between data points, by using
24+
``np.histogram2d`` and ``plt.pcolormesh``.
25+
"""
26+
from copy import copy
27+
import time
28+
29+
import numpy as np
30+
import numpy.matlib
31+
import matplotlib.pyplot as plt
32+
from matplotlib.colors import LogNorm
33+
34+
fig, axes = plt.subplots(nrows=3, figsize=(6, 8), constrained_layout=True)
35+
36+
# Make some data; a 1D random walk + small fraction of sine waves
37+
num_series = 1000
38+
num_points = 100
39+
SNR = 0.10 # Signal to Noise Ratio
40+
x = np.linspace(0, 4 * np.pi, num_points)
41+
# Generate unbiased Gaussian random walks
42+
Y = np.cumsum(np.random.randn(num_series, num_points), axis=-1)
43+
# Generate sinusoidal signals
44+
num_signal = int(round(SNR * num_series))
45+
phi = (np.pi / 8) * np.random.randn(num_signal, 1) # small random offest
46+
Y[-num_signal:] = (
47+
np.sqrt(np.arange(num_points))[None, :] # random walk RMS scaling factor
48+
* (np.sin(x[None, :] - phi)
49+
+ 0.05 * np.random.randn(num_signal, num_points)) # small random noise
50+
)
51+
52+
53+
# Plot series using `plot` and a small value of `alpha`. With this view it is
54+
# very difficult to observe the sinusoidal behavior because of how many
55+
# overlapping series there are. It also takes a bit of time to run because so
56+
# many individual artists need to be generated.
57+
tic = time.time()
58+
axes[0].plot(x, Y.T, color="C0", alpha=0.1)
59+
toc = time.time()
60+
axes[0].set_title("Line plot with alpha")
61+
print(f"{toc-tic:.3f} sec. elapsed")
62+
63+
64+
# Now we will convert the multiple time series into a histogram. Not only will
65+
# the hidden signal be more visible, but it is also a much quicker procedure.
66+
tic = time.time()
67+
# Linearly interpolate between the points in each time series
68+
num_fine = 800
69+
x_fine = np.linspace(x.min(), x.max(), num_fine)
70+
y_fine = np.empty((num_series, num_fine), dtype=float)
71+
for i in range(num_series):
72+
y_fine[i, :] = np.interp(x_fine, x, Y[i, :])
73+
y_fine = y_fine.flatten()
74+
x_fine = np.matlib.repmat(x_fine, num_series, 1).flatten()
75+
76+
77+
# Plot (x, y) points in 2d histogram with log colorscale
78+
# It is pretty evident that there is some kind of structure under the noise
79+
# You can tune vmax to make signal more visible
80+
cmap = copy(plt.cm.plasma)
81+
cmap.set_bad(cmap(0))
82+
h, xedges, yedges = np.histogram2d(x_fine, y_fine, bins=[400, 100])
83+
pcm = axes[1].pcolormesh(xedges, yedges, h.T, cmap=cmap,
84+
norm=LogNorm(vmax=1.5e2), rasterized=True)
85+
fig.colorbar(pcm, ax=axes[1], label="# points", pad=0)
86+
axes[1].set_title("2d histogram and log color scale")
87+
88+
# Same data but on linear color scale
89+
pcm = axes[2].pcolormesh(xedges, yedges, h.T, cmap< 5DBC span class=pl-c1>=cmap,
90+
vmax=1.5e2, rasterized=True)
91+
fig.colorbar(pcm, ax=axes[2], label="# points", pad=0)
92+
axes[2].set_title("2d histogram and linear color scale")
93+
94+
toc = time.time()
95+
print(f"{toc-tic:.3f} sec. elapsed")
96+
plt.show()

0 commit comments

Comments
 (0)
0