Mirror Chart
Online vs In-Store Pricing
Mirror density comparing retail prices with savings analysis
Output
Python
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import gaussian_kde
np.random.seed(777)
BG_COLOR = '#ffffff'
TEXT_COLOR = '#1f2937'
online = np.random.lognormal(3.8, 0.45, 800)
instore = np.random.lognormal(4.0, 0.42, 800)
online = online[online < 180]
instore = instore[instore < 180]
fig, ax = plt.subplots(figsize=(12, 7), facecolor=BG_COLOR)
ax.set_facecolor(BG_COLOR)
x = np.linspace(0, 180, 500)
kde_o = gaussian_kde(online)
y_o = kde_o(x)
ax.fill_between(x, y_o, alpha=0.25, color='#27D3F5')
ax.plot(x, y_o, color='#27D3F5', linewidth=3, label='Online (avg=$%.0f)' % np.mean(online))
kde_i = gaussian_kde(instore)
y_i = kde_i(x) * -1
ax.fill_between(x, y_i, alpha=0.25, color='#F5276C')
ax.plot(x, y_i, color='#F5276C', linewidth=3, label='In-Store (avg=$%.0f)' % np.mean(instore))
ax.axhline(0, color=TEXT_COLOR, linewidth=1.5)
ax.axvline(np.mean(online), color='#27D3F5', linestyle='--', alpha=0.5, linewidth=1.5)
ax.axvline(np.mean(instore), color='#F5276C', linestyle='--', alpha=0.5, linewidth=1.5)
avg_savings = np.mean(instore) - np.mean(online)
pct_savings = (avg_savings / np.mean(instore)) * 100
ax.text(np.mean(online), max(y_o)*0.6, 'Save $%.0f (%.0f%%)' % (avg_savings, pct_savings),
fontsize=14, color='#22c55e', fontweight='bold', ha='center',
bbox=dict(boxstyle='round,pad=0.4', facecolor=BG_COLOR, edgecolor='#22c55e', lw=2))
ax.annotate('', xy=(np.mean(online), max(y_o)*0.35), xytext=(np.mean(instore), max(y_o)*0.35),
arrowprops=dict(arrowstyle='<-', color='#22c55e', lw=2.5))
stats = 'P90: Online $%.0f vs In-Store $%.0f' % (np.percentile(online, 90), np.percentile(instore, 90))
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('Product Price ($)', fontsize=12, color=TEXT_COLOR, fontweight='500')
ax.set_title('Retail Price Comparison: Online vs In-Store', 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
☕