Mirror Chart

Morning vs Evening Commute Time

Mirror histogram comparing rush hour commute distributions with delay analysis

Output
Morning vs Evening Commute Time
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

Did this help you?

Support PyLucid to keep it free & growing

Support