Monday, June 15, 2026

x̄ - > Multi-panel data visualization


 import numpy as np
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec

np.random.seed(7)

months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct']
vals = np.array([38,44,49,57,61,68,74,79,86,92])

line = np.cumsum(np.random.normal(0, 1, 60)) + 20

x = np.linspace(0, 10, 90)
y = 0.6 * x + np.random.normal(0, 0.35, 90) + 2
sizes = np.random.randint(20, 180, 90)

heat = np.random.randint(0, 100, (8, 12))

fig = plt.figure(figsize=(14, 7), dpi=200, facecolor='#f5f1ea')
gs = GridSpec(3, 4, figure=fig, wspace=0.35, hspace=0.35)

# 1. Horizontal bar chart
ax1 = fig.add_subplot(gs[0:2, 0])
ax1.barh(months[::-1], vals[::-1], color='#4d89c7')
ax1.set_title('Keywords per month', fontsize=12)
ax1.tick_params(labelsize=8)
ax1.grid(axis='x', alpha=0.2)

# 2. Scatter cluster view
ax2 = fig.add_subplot(gs[0, 1:3])
ax2.scatter(
    x, y,
    c=np.linspace(0, 1, 90),
    s=sizes,
    cmap='tab20',
    alpha=0.85,
    edgecolor='white',
    linewidth=0.4
)
ax2.set_title('Scatter cluster view', fontsize=12)
ax2.tick_params(labelsize=8)
ax2.grid(alpha=0.15)

# 3. Bubble cluster
ax3 = fig.add_subplot(gs[0:2, 3])
cols = np.random.choice(
    ['#f28e2b', '#59a14f', '#e15759', '#4e79a7', '#b07aa1'],
    120
)
ax3.scatter(
    np.random.randn(120),
    np.random.randn(120),
    s=np.random.randint(20, 300, 120),
    c=cols,
    alpha=0.7
)
ax3.set_title('Bubble cluster', fontsize=12)
ax3.tick_params(labelsize=8)
ax3.grid(alpha=0.15)

# 4. Line chart
ax4 = fig.add_subplot(gs[1, 1:3])
ax4.plot(line, color='#2a6f97', lw=1.6)
ax4.set_title('Aggregated trend over time', fontsize=12)
ax4.tick_params(labelsize=8)
ax4.grid(alpha=0.2)

# 5. Weekday scatter
ax5 = fig.add_subplot(gs[2, 0:2])
ax5.scatter(
    np.repeat(range(7), 20),
    np.random.rand(140),
    s=6,
    alpha=0.45,
    color='#4878cf'
)
ax5.set_title('Keywords per weekday', fontsize=12)
ax5.tick_params(labelsize=8)
ax5.grid(alpha=0.15)

# 6. Heatmap
ax6 = fig.add_subplot(gs[2, 2:4])
ax6.imshow(heat, cmap='RdYlGn', aspect='auto')
ax6.set_title('Heatmap summary', fontsize=12)
ax6.tick_params(labelsize=8)

# remove spines for a clean dashboard style
for ax in [ax1, ax2, ax3, ax4, ax5, ax6]:
    for spine in ax.spines.values():
        spine.set_visible(False)

plt.show()

No comments:

Meet the Authors
Zacharia Maganga’s blog features multiple contributors with clear activity status.
Active ✔
πŸ§‘‍πŸ’»
Zacharia Maganga
Lead Author
Active ✔
πŸ‘©‍πŸ’»
Linda Bahati
Co‑Author
Active ✔
πŸ‘¨‍πŸ’»
Jefferson Mwangolo
Co‑Author
Inactive ✖
πŸ‘©‍πŸŽ“
Florence Wavinya
Guest Author
Inactive ✖
πŸ‘©‍πŸŽ“
Esther Njeri
Guest Author
Inactive ✖
πŸ‘©‍πŸŽ“
Clemence Mwangolo
Guest Author

Followers

Support This Blog
Tap Donate now here to donate or go to donate on top menu to scan QR and support this site.
Donate Now