|
| 1 | +""" |
| 2 | +ridgeline-basic: Ridgeline Plot |
| 3 | +Library: matplotlib |
| 4 | +""" |
| 5 | + |
| 6 | +import matplotlib.pyplot as plt |
| 7 | +import numpy as np |
| 8 | + |
| 9 | + |
| 10 | +# Data - Monthly temperature distributions |
| 11 | +np.random.seed(42) |
| 12 | +months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] |
| 13 | + |
| 14 | +# Generate temperature data with seasonal variation |
| 15 | +temperature_data = [] |
| 16 | +base_temps = [2, 4, 8, 13, 17, 21, 24, 23, 19, 13, 7, 3] |
| 17 | +for i in range(len(months)): |
| 18 | + temperature_data.append(np.random.normal(base_temps[i], 4, 200)) |
| 19 | + |
| 20 | +# Color palette - gradient from cool to warm |
| 21 | +colors = [ |
| 22 | + "#306998", |
| 23 | + "#3A7CA5", |
| 24 | + "#4A90B2", |
| 25 | + "#5BA4BF", |
| 26 | + "#7BB8C9", |
| 27 | + "#9CCCD3", |
| 28 | + "#FFD43B", |
| 29 | + "#FFCC33", |
| 30 | + "#F9B926", |
| 31 | + "#F9A619", |
| 32 | + "#F97316", |
| 33 | + "#DC2626", |
| 34 | +] |
| 35 | + |
| 36 | +# Create plot |
| 37 | +fig, ax = plt.subplots(figsize=(16, 9)) |
| 38 | + |
| 39 | +# X-axis range for KDE |
| 40 | +x_range = np.linspace(-10, 35, 500) |
| 41 | + |
| 42 | +# KDE bandwidth (Silverman's rule-of-thumb) |
| 43 | +bandwidth = 2.0 |
| 44 | + |
| 45 | +# Overlap factor and scale |
| 46 | +overlap = 0.25 |
| 47 | +scale = 0.85 |
| 48 | + |
| 49 | +# Plot each distribution from top to bottom |
| 50 | +for i, month in enumerate(reversed(months)): |
| 51 | + idx = len(months) - 1 - i |
| 52 | + data = temperature_data[idx] |
| 53 | + |
| 54 | + # Compute Gaussian KDE (inline, no scipy) |
| 55 | + n = len(data) |
| 56 | + density = np.zeros_like(x_range) |
| 57 | + for d in data: |
| 58 | + density += np.exp(-0.5 * ((x_range - d) / bandwidth) ** 2) |
| 59 | + density /= n * bandwidth * np.sqrt(2 * np.pi) |
| 60 | + |
| 61 | + # Normalize density |
| 62 | + density = density / density.max() * scale |
| 63 | + |
| 64 | + # Vertical offset |
| 65 | + offset = i * overlap |
| 66 | + |
| 67 | + # Plot filled density |
| 68 | + ax.fill_between(x_range, offset, density + offset, alpha=0.7, color=colors[idx], edgecolor="white", linewidth=1.5) |
| 69 | + |
| 70 | + # Add month label |
| 71 | + ax.text(-12, offset + 0.15, month, fontsize=16, fontweight="bold", va="center", ha="right") |
| 72 | + |
| 73 | +# Styling |
| 74 | +ax.set_xlabel("Temperature (°C)", fontsize=20) |
| 75 | +ax.set_title("Monthly Temperature Distribution", fontsize=20, fontweight="bold", pad=20) |
| 76 | + |
| 77 | +# Clean up axes |
| 78 | +ax.set_xlim(-15, 35) |
| 79 | +ax.set_ylim(-0.1, len(months) * overlap + scale + 0.1) |
| 80 | +ax.spines["top"].set_visible(False) |
| 81 | +ax.spines["right"].set_visible(False) |
| 82 | +ax.spines["left"].set_visible(False) |
| 83 | +ax.set_yticks([]) |
| 84 | +ax.tick_params(axis="x", labelsize=16) |
| 85 | + |
| 86 | +# Add subtle grid on x-axis only |
| 87 | +ax.xaxis.grid(True, alpha=0.3, linestyle="--") |
| 88 | + |
| 89 | +plt.tight_layout() |
| 90 | +plt.savefig("plot.png", dpi=300, bbox_inches="tight") |
0 commit comments