Skip to content

Commit ba078e4

Browse files
feat(matplotlib): implement ridgeline-basic (#542)
## Summary Implements `ridgeline-basic` for **matplotlib**. **Parent Issue:** #539 **Base Branch:** `plot/ridgeline-basic` ## Files - `plots/ridgeline-basic/implementations/matplotlib.py` ## Preview Preview will be uploaded to GCS staging after this workflow completes. Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent 6e56842 commit ba078e4

File tree

1 file changed

+90
-0
lines changed

1 file changed

+90
-0
lines changed
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
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

Comments
 (0)