Violin Plot
Clinical Trial Drug Response
Biomarker reduction distribution with therapeutic threshold and response rates
Output
Python
import matplotlib.pyplot as plt
import numpy as np
# Clinical trial response data
np.random.seed(42)
treatments = ['Placebo', 'Drug A\n(10mg)', 'Drug A\n(25mg)', 'Drug A\n(50mg)', 'Drug B\n(25mg)']
# Simulating biomarker reduction (higher = better)
responses = [
np.random.normal(5, 8, 150), # Placebo
np.random.normal(15, 10, 150), # Drug A low
np.random.normal(28, 12, 150), # Drug A mid
np.random.normal(35, 15, 150), # Drug A high
np.random.normal(32, 9, 150), # Drug B
]
# Clinical threshold
therapeutic_threshold = 20
# Create figure
fig, ax = plt.subplots(figsize=(12, 7), facecolor='white')
# Color palette
colors = ['#9CA3AF', '#93C5FD', '#60A5FA', '#3B82F6', '#8B5CF6']
vp = ax.violinplot(responses, positions=range(len(treatments)), widths=0.7,
showmeans=False, showmedians=False, showextrema=False)
for i, body in enumerate(vp['bodies']):
body.set_facecolor(colors[i])
body.set_edgecolor('white')
body.set_linewidth(2)
body.set_alpha(0.75)
# Add response rate annotation (% above threshold)
for i, resp in enumerate(responses):
response_rate = (resp >= therapeutic_threshold).mean() * 100
median = np.median(resp)
# Median marker
ax.scatter(i, median, c='white', s=100, zorder=10,
edgecolor=colors[i], linewidth=2.5)
# Response rate box
ax.annotate(f'{response_rate:.0f}%', xy=(i, 55),
ha='center', fontsize=11, fontweight='bold',
color='#10B981' if response_rate > 50 else '#6B7280',
bbox=dict(boxstyle='round,pad=0.3', facecolor='white',
edgecolor='#E5E7EB'))
# Therapeutic threshold line
ax.axhline(therapeutic_threshold, color='#10B981', linewidth=2,
linestyle='--', alpha=0.8, zorder=0)
ax.text(4.6, therapeutic_threshold + 1, 'Therapeutic\nThreshold',
fontsize=9, color='#10B981', fontweight='500', va='bottom')
# Styling
ax.set_xticks(range(len(treatments)))
ax.set_xticklabels(treatments, fontsize=10, fontweight='500')
ax.set_ylabel('Biomarker Reduction (%)', fontsize=12, fontweight='500', color='#374151')
ax.set_ylim(-30, 70)
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['left'].set_color('#E5E7EB')
ax.spines['bottom'].set_color('#E5E7EB')
ax.tick_params(colors='#6B7280', labelsize=10)
ax.yaxis.grid(True, linestyle='--', alpha=0.3, color='#9CA3AF')
# Label
ax.text(-0.5, 62, 'Response Rate', fontsize=10, color='#6B7280', fontweight='500')
plt.tight_layout()
plt.show()
Library
Matplotlib
Category
Statistical
More Violin Plot examples
☕