Mirror Chart
Desktop vs Mobile Performance
Mirror density comparing response times with SLA threshold and percentile annotations
Output
Python
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import gaussian_kde
np.random.seed(1968)
BG_COLOR = '#ffffff'
TEXT_COLOR = '#1f2937'
desktop = np.random.lognormal(2.0, 0.5, 1000)
mobile = np.random.lognormal(2.5, 0.6, 1200)
desktop = desktop[desktop < 50]
mobile = mobile[mobile < 80]
fig, ax = plt.subplots(figsize=(12, 7), facecolor=BG_COLOR)
ax.set_facecolor(BG_COLOR)
x = np.linspace(0, 80, 400)
kde_d = gaussian_kde(desktop)
y_d = kde_d(x)
ax.fill_between(x, y_d, alpha=0.3, color='#4927F5')
ax.plot(x, y_d, color='#4927F5', linewidth=2, label='Desktop')
kde_m = gaussian_kde(mobile)
y_m = kde_m(x) * -1
ax.fill_between(x, y_m, alpha=0.3, color='#F5276C')
ax.plot(x, y_m, color='#F5276C', linewidth=2, label='Mobile')
ax.axhline(0, color=TEXT_COLOR, linewidth=1.5)
p50_d = np.percentile(desktop, 50)
p50_m = np.percentile(mobile, 50)
p90_d = np.percentile(desktop, 90)
p90_m = np.percentile(mobile, 90)
ax.axvline(p50_d, color='#4927F5', linestyle='--', linewidth=1.5, alpha=0.7)
ax.axvline(p50_m, color='#F5276C', linestyle='--', linewidth=1.5, alpha=0.7)
core_web_vital = 2.5
ax.axvline(core_web_vital, color='#22c55e', linestyle=':', linewidth=2)
ax.text(core_web_vital + 0.5, 0.08, 'Good (2.5s)', color='#22c55e', fontsize=9, rotation=90)
stats_text = 'Performance (P50/P90):\nDesktop: %.1fs / %.1fs\nMobile: %.1fs / %.1fs' % (p50_d, p90_d, p50_m, p90_m)
ax.text(0.02, 0.98, stats_text.replace('\n', chr(10)), transform=ax.transAxes, fontsize=10,
color=TEXT_COLOR, verticalalignment='top', fontfamily='monospace',
bbox=dict(boxstyle='round,pad=0.5', facecolor='#f8fafc', edgecolor='#e5e7eb', alpha=0.9))
pct_good_d = (desktop < core_web_vital).sum() / len(desktop) * 100
pct_good_m = (mobile < core_web_vital).sum() / len(mobile) * 100
ax.text(0.98, 0.98, 'Good CWV: Desktop %.0f%% | Mobile %.0f%%' % (pct_good_d, pct_good_m),
transform=ax.transAxes, fontsize=10, color='#6b7280', ha='right', va='top')
ax.set_xlabel('Page Load Time (seconds)', fontsize=12, color=TEXT_COLOR, fontweight='500')
ax.set_ylabel('Density', fontsize=12, color=TEXT_COLOR, fontweight='500')
ax.set_title('Web Performance: Desktop vs Mobile', fontsize=14,
color=TEXT_COLOR, fontweight='bold', pad=15)
ax.tick_params(colors='#374151', labelsize=10)
for spine in ax.spines.values():
spine.set_color('#e5e7eb')
ax.legend(loc='upper right', facecolor=BG_COLOR, edgecolor='#e5e7eb',
labelcolor=TEXT_COLOR, fontsize=10)
ax.set_xlim(0, 50)
plt.tight_layout()
plt.show()
Library
Matplotlib
Category
Statistical
☕