Violin Plot

Crop Yield Comparison

Conventional vs regenerative farming yield distributions

Output
Crop Yield Comparison
Python
import matplotlib.pyplot as plt
import numpy as np

# Crop yield data (tons per hectare)
np.random.seed(42)
crops = ['Wheat', 'Rice', 'Corn', 'Soybean', 'Cotton']
# Yield by farming method: conventional vs regenerative
conventional = [
    np.random.normal(3.2, 0.6, 100),
    np.random.normal(4.5, 0.8, 100),
    np.random.normal(9.5, 1.5, 100),
    np.random.normal(2.8, 0.5, 100),
    np.random.normal(1.6, 0.3, 100),
]
regenerative = [
    np.random.normal(3.5, 0.5, 100),
    np.random.normal(4.8, 0.6, 100),
    np.random.normal(10.2, 1.2, 100),
    np.random.normal(3.1, 0.4, 100),
    np.random.normal(1.8, 0.25, 100),
]

# Colors
color_conv = '#78716C'
color_regen = '#22C55E'

# Create figure with earth tones background
fig, ax = plt.subplots(figsize=(12, 7), facecolor='#FFFBEB')
ax.set_facecolor('#FFFBEB')

positions_conv = np.arange(len(crops)) - 0.2
positions_regen = np.arange(len(crops)) + 0.2

# Conventional violins
vp1 = ax.violinplot(conventional, positions=positions_conv, widths=0.35,
                    showmeans=False, showmedians=False, showextrema=False)
for body in vp1['bodies']:
    body.set_facecolor(color_conv)
    body.set_edgecolor('white')
    body.set_linewidth(1.5)
    body.set_alpha(0.7)

# Regenerative violins
vp2 = ax.violinplot(regenerative, positions=positions_regen, widths=0.35,
                    showmeans=False, showmedians=False, showextrema=False)
for body in vp2['bodies']:
    body.set_facecolor(color_regen)
    body.set_edgecolor('white')
    body.set_linewidth(1.5)
    body.set_alpha(0.7)

# Add yield improvement arrows
for i in range(len(crops)):
    conv_med = np.median(conventional[i])
    regen_med = np.median(regenerative[i])
    improvement = ((regen_med - conv_med) / conv_med) * 100
    
    # Medians
    ax.scatter(positions_conv[i], conv_med, c='white', s=60, zorder=10,
               edgecolor=color_conv, linewidth=2)
    ax.scatter(positions_regen[i], regen_med, c='white', s=60, zorder=10,
               edgecolor=color_regen, linewidth=2)
    
    # Improvement annotation
    y_pos = max(conv_med, regen_med) + 0.8
    ax.annotate(f'+{improvement:.0f}%', xy=(i, y_pos),
                ha='center', fontsize=10, fontweight='bold',
                color='#15803D',
                bbox=dict(boxstyle='round,pad=0.2', facecolor='#DCFCE7',
                         edgecolor='#22C55E', alpha=0.9))

# Legend
ax.scatter([], [], c=color_conv, s=100, label='Conventional', marker='s')
ax.scatter([], [], c=color_regen, s=100, label='Regenerative', marker='s')
ax.legend(loc='upper right', frameon=True, facecolor='white',
          edgecolor='#E5E7EB', fontsize=11)

# Styling
ax.set_xticks(range(len(crops)))
ax.set_xticklabels(crops, fontsize=12, fontweight='600', color='#44403C')
ax.set_ylabel('Yield (tons/hectare)', fontsize=12, fontweight='500', color='#57534E')
ax.set_ylim(0, 14)

ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['left'].set_color('#D6D3D1')
ax.spines['bottom'].set_color('#D6D3D1')
ax.tick_params(colors='#78716C', labelsize=10)
ax.yaxis.grid(True, linestyle='--', alpha=0.4, color='#D6D3D1')

plt.tight_layout()
plt.show()
Library

Matplotlib

Category

Statistical

Did this help you?

Support PyLucid to keep it free & growing

Support