ANOVA Violin Plot

Clinical Trial Drug Response ANOVA

Comparing drug efficacy across three treatment groups with statistical significance testing.

Output
Clinical Trial Drug Response ANOVA
Python
import matplotlib.pyplot as plt
import numpy as np
import scipy.stats as stats

np.random.seed(42)

# Clinical trial data: response scores (0-100) for three drug treatments
placebo = np.random.normal(45, 15, 120)
drug_a = np.random.normal(62, 12, 120)
drug_b = np.random.normal(71, 14, 120)

# ANOVA test
F_stat, p_value = stats.f_oneway(placebo, drug_a, drug_b)

# Create figure with dark theme
fig, ax = plt.subplots(figsize=(12, 7), facecolor='#0a0a0f')
ax.set_facecolor('#0a0a0f')

# Colors from neon palette
colors = ['#F5276C', '#27D3F5', '#6CF527']

# Create violin plot
parts = ax.violinplot([placebo, drug_a, drug_b], positions=[1, 2, 3], 
                       showmeans=True, showmedians=True)

# Style the violins
for i, pc in enumerate(parts['bodies']):
    pc.set_facecolor(colors[i])
    pc.set_alpha(0.7)
    pc.set_edgecolor(colors[i])
    pc.set_linewidth(2)

# Style other elements
parts['cmeans'].set_color('#F5D327')
parts['cmeans'].set_linewidth(2)
parts['cmedians'].set_color('white')
parts['cmedians'].set_linewidth(1.5)
for partname in ['cbars', 'cmins', 'cmaxes']:
    parts[partname].set_color('#666666')
    parts[partname].set_linewidth(1)

# Add statistical annotation box - moved to bottom left
stats_text = f"One-Way ANOVA Results\n" + "─" * 22 + f"\nF-statistic: {F_stat:.2f}\np-value: {p_value:.2e}"
bbox_props = dict(boxstyle="round,pad=0.5", facecolor='#1a1a2e', edgecolor='#27D3F5', alpha=0.9)
ax.text(0.02, 0.02, stats_text, transform=ax.transAxes, fontsize=11, color='white',
        verticalalignment='bottom', fontfamily='monospace', bbox=bbox_props)

# Add mean annotations - positioned to the right of violins
means = [placebo.mean(), drug_a.mean(), drug_b.mean()]
labels = ['Placebo', 'Drug A', 'Drug B']
for i, (mean, label) in enumerate(zip(means, labels)):
    ax.annotate(f'μ = {mean:.1f}', xy=(i+1, mean), xytext=(i+1.25, mean),
                fontsize=10, color=colors[i], fontweight='bold',
                arrowprops=dict(arrowstyle='->', color=colors[i], lw=1.5))

# Significance brackets
if p_value < 0.05:
    ax.plot([1, 1, 3, 3], [98, 102, 102, 98], 'w-', lw=1.5)
    ax.text(2, 104, '***' if p_value < 0.001 else '**' if p_value < 0.01 else '*',
            ha='center', color='#F5D327', fontsize=14, fontweight='bold')

# Styling
ax.set_xticks([1, 2, 3])
ax.set_xticklabels(labels, fontsize=12, color='white')
ax.set_ylabel('Treatment Response Score', fontsize=12, color='white', fontweight='500')
ax.set_title('Clinical Trial: Drug Efficacy Comparison\nPhase III Randomized Controlled Trial', 
             fontsize=14, color='white', fontweight='bold', pad=20)

ax.tick_params(colors='#888888', labelsize=10)
for spine in ax.spines.values():
    spine.set_color('#333333')
ax.yaxis.grid(True, color='#1a1a2e', linewidth=0.5, alpha=0.5)
ax.set_axisbelow(True)
ax.set_ylim(0, 115)

plt.tight_layout()
plt.show()
Library

Matplotlib

Category

Statistical

Did this help you?

Support PyLucid to keep it free & growing

Support