ANOVA Violin Plot

Sleep Quality by Age Group ANOVA

Analyzing sleep efficiency distributions across different age demographics.

Output
Sleep Quality by Age Group ANOVA
Python
import matplotlib.pyplot as plt
import numpy as np
import scipy.stats as stats

np.random.seed(1717)

# Sleep efficiency percentage
young_adults = np.random.normal(88, 6, 100)
middle_age = np.random.normal(82, 8, 100)
older_adults = np.random.normal(75, 10, 100)
seniors = np.random.normal(68, 12, 100)

# Clip to valid percentages
young_adults = np.clip(young_adults, 50, 100)
middle_age = np.clip(middle_age, 45, 100)
older_adults = np.clip(older_adults, 40, 100)
seniors = np.clip(seniors, 35, 100)

F_stat, p_value = stats.f_oneway(young_adults, middle_age, older_adults, seniors)

fig, ax = plt.subplots(figsize=(12, 7), facecolor='#ffffff')
ax.set_facecolor('#ffffff')

colors = ['#6CF527', '#27D3F5', '#F5B027', '#F5276C']

parts = ax.violinplot([young_adults, middle_age, older_adults, seniors], 
                       positions=[1, 2, 3, 4], showmeans=True, showmedians=True, widths=0.7)

for i, pc in enumerate(parts['bodies']):
    pc.set_facecolor(colors[i])
    pc.set_alpha(0.6)
    pc.set_edgecolor(colors[i])
    pc.set_linewidth(2)

parts['cmeans'].set_color('#5314E6')
parts['cmeans'].set_linewidth(2.5)
parts['cmedians'].set_color('#1f2937')
for partname in ['cbars', 'cmins', 'cmaxes']:
    parts[partname].set_color('#9ca3af')

# Sleep thresholds
ax.axhline(y=85, color='#22c55e', linestyle='--', alpha=0.7, linewidth=1.5)
ax.axhline(y=70, color='#f97316', linestyle='--', alpha=0.7, linewidth=1.5)
ax.text(4.45, 85, 'Good', fontsize=8, color='#22c55e', va='center')
ax.text(4.45, 70, 'Fair', fontsize=8, color='#f97316', va='center')

labels = ['18-30y', '31-50y', '51-65y', '65+y']

# REM sleep at bottom
rem_pct = ['25%', '22%', '18%', '15%']
means = [young_adults.mean(), middle_age.mean(), older_adults.mean(), seniors.mean()]
for i, (rem, mean, color) in enumerate(zip(rem_pct, means, colors)):
    ax.text(i+1, 32, f'REM:{rem} | μ={mean:.0f}%', ha='center', fontsize=8, color=color)

# Stats at top
stats_text = f"ANOVA: F={F_stat:.2f}, p={p_value:.2e} | Trend: Decline with age"
bbox = dict(boxstyle="round,pad=0.3", facecolor='#f0fdf4', edgecolor='#6CF527', lw=2)
ax.text(0.5, 1.02, stats_text, transform=ax.transAxes, fontsize=10, color='#1f2937',
        ha='center', va='bottom', fontfamily='monospace', bbox=bbox)

ax.set_xticks([1, 2, 3, 4])
ax.set_xticklabels(labels, fontsize=11, color='#1f2937')
ax.set_ylabel('Sleep Efficiency (%)', fontsize=12, color='#1f2937', fontweight='500')
ax.set_title('Sleep Quality Across Age Groups\nPolysomnography Study (N=400)', 
             fontsize=14, color='#1f2937', fontweight='bold', pad=25)

ax.tick_params(colors='#374151')
for spine in ax.spines.values():
    spine.set_color('#e5e7eb')
ax.yaxis.grid(True, color='#f3f4f6', linewidth=0.8)
ax.set_axisbelow(True)
ax.set_ylim(28, 105)

plt.tight_layout()
plt.show()
Library

Matplotlib

Category

Statistical

Did this help you?

Support PyLucid to keep it free & growing

Support