Mirror Chart

Beginner vs Advanced Student Scores

Mirror histogram comparing exam performance with pass rate analysis

Output
Beginner vs Advanced Student Scores
Python
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import gaussian_kde

np.random.seed(1979)
BG_COLOR = '#0a0a0f'
TEXT_COLOR = 'white'

beginners = np.random.normal(65, 12, 800)
advanced = np.random.normal(85, 8, 600)
beginners = beginners[(beginners >= 30) & (beginners <= 100)]
advanced = advanced[(advanced >= 50) & (advanced <= 100)]

fig, ax = plt.subplots(figsize=(12, 7), facecolor=BG_COLOR)
ax.set_facecolor(BG_COLOR)

x = np.linspace(30, 100, 400)

kde_b = gaussian_kde(beginners)
y_b = kde_b(x)
ax.fill_between(x, y_b, alpha=0.3, color='#F5276C')
ax.plot(x, y_b, color='#F5276C', linewidth=4, alpha=0.3)
ax.plot(x, y_b, color='#F5276C', linewidth=2, label='Beginners (n=%d)' % len(beginners))

kde_a = gaussian_kde(advanced)
y_a = kde_a(x) * -1
ax.fill_between(x, y_a, alpha=0.3, color='#27D3F5')
ax.plot(x, y_a, color='#27D3F5', linewidth=4, alpha=0.3)
ax.plot(x, y_a, color='#27D3F5', linewidth=2, label='Advanced (n=%d)' % len(advanced))

ax.axhline(0, color='#333', linewidth=1.5)

med_b = np.median(beginners)
med_a = np.median(advanced)
ax.axvline(med_b, color='#F5276C', linestyle='--', linewidth=1.5, alpha=0.7)
ax.axvline(med_a, color='#27D3F5', linestyle='--', linewidth=1.5, alpha=0.7)

improvement = med_a - med_b
ax.annotate('', xy=(med_a, 0.02), xytext=(med_b, 0.02),
            arrowprops=dict(arrowstyle='<->', color='#F5B027', lw=2))
ax.text((med_b + med_a)/2, 0.025, '+%.1f pts' % improvement, 
        color='#F5B027', fontsize=11, ha='center', fontweight='bold')

pass_rate_b = (beginners >= 70).sum() / len(beginners) * 100
pass_rate_a = (advanced >= 70).sum() / len(advanced) * 100
stats_text = 'Pass Rate (70+):\nBeginners: %.0f%%\nAdvanced: %.0f%%' % (pass_rate_b, pass_rate_a)
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='#1a1a2e', edgecolor='#333', alpha=0.9))

ax.set_xlabel('Test Score', fontsize=12, color=TEXT_COLOR, fontweight='500')
ax.set_ylabel('Density', fontsize=12, color=TEXT_COLOR, fontweight='500')
ax.set_title('Student Achievement: Beginner vs Advanced', fontsize=14, 
             color=TEXT_COLOR, fontweight='bold', pad=15)

ax.tick_params(colors='#888', labelsize=10)
for spine in ax.spines.values():
    spine.set_color('#333')

ax.legend(loc='upper right', facecolor='#1a1a2e', edgecolor='#333', 
          labelcolor=TEXT_COLOR, fontsize=10)
ax.set_xlim(30, 100)
plt.tight_layout()
plt.show()
Library

Matplotlib

Category

Statistical

Did this help you?

Support PyLucid to keep it free & growing

Support