Mirror Chart
Morning vs Evening Commute Time
Mirror histogram comparing rush hour commute distributions with delay analysis
Output
Python
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(666)
BG_COLOR = '#ffffff'
TEXT_COLOR = '#1f2937'
morning = np.random.gamma(4, 7, 700) + 12
evening = np.random.gamma(5, 8, 700) + 18
fig, ax = plt.subplots(figsize=(12, 7), facecolor=BG_COLOR)
ax.set_facecolor(BG_COLOR)
bins = np.linspace(0, 100, 35)
bin_width = bins[1] - bins[0]
centers = (bins[:-1] + bins[1:]) / 2
h1, _ = np.histogram(morning, bins=bins, density=True)
ax.bar(centers, h1, width=bin_width*0.85, color='#F5B027', alpha=0.7,
edgecolor='#F5B027', linewidth=1.5, label='Morning (avg=%.0f min)' % np.mean(morning))
h2, _ = np.histogram(evening, bins=bins, density=True)
ax.bar(centers, -h2, width=bin_width*0.85, color='#4927F5', alpha=0.7,
edgecolor='#4927F5', linewidth=1.5, label='Evening (avg=%.0f min)' % np.mean(evening))
ax.axhline(0, color=TEXT_COLOR, linewidth=1.5)
normal = 30
ax.axvline(normal, color='#22c55e', linestyle='--', linewidth=2, alpha=0.7)
ax.text(normal + 2, max(h1)*0.9, 'Target 30 min', color='#22c55e', fontsize=9, fontweight='bold')
heavy = 60
ax.axvspan(heavy, 100, alpha=0.08, color='#ef4444')
ax.text(75, max(h1)*0.7, 'Heavy Traffic', color='#ef4444', fontsize=9, ha='center')
morning_ontime = (morning <= normal).mean() * 100
evening_ontime = (evening <= normal).mean() * 100
delay = np.mean(evening) - np.mean(morning)
ax.text(80, 0, '+%.0f min delay' % delay, fontsize=14, color='#F5276C',
fontweight='bold', ha='center', va='center',
bbox=dict(boxstyle='round,pad=0.4', facecolor=BG_COLOR, edgecolor='#F5276C', lw=2))
stats = 'On-Time: Morning %.0f%% | Evening %.0f%%' % (morning_ontime, evening_ontime)
ax.text(0.5, 0.98, stats, transform=ax.transAxes, ha='center', va='top',
fontsize=10, color='#6b7280', fontfamily='monospace',
bbox=dict(boxstyle='round,pad=0.4', facecolor=BG_COLOR, edgecolor='#e5e7eb', lw=1.5))
ax.set_xlabel('Commute Time (minutes)', fontsize=12, color=TEXT_COLOR, fontweight='500')
ax.set_title('Rush Hour Analysis: Morning vs Evening', fontsize=16, color=TEXT_COLOR, fontweight='bold', pad=25)
ax.tick_params(colors=TEXT_COLOR, labelsize=10)
ax.set_yticks([])
for spine in ['top', 'right']:
ax.spines[spine].set_visible(False)
for spine in ['bottom', 'left']:
ax.spines[spine].set_color('#e5e7eb')
ax.legend(loc='upper right', facecolor=BG_COLOR, edgecolor='#e5e7eb', labelcolor=TEXT_COLOR, fontsize=10)
plt.tight_layout()
plt.show()
Library
Matplotlib
Category
Statistical
☕