Skip to content

Commit 7624656

Browse files
feat(matplotlib): implement andrews-curves (#2887)
## Implementation: `andrews-curves` - matplotlib Implements the **matplotlib** version of `andrews-curves`. **File:** `plots/andrews-curves/implementations/matplotlib.py` **Parent Issue:** #2859 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/20608490813)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent 933f9ad commit 7624656

2 files changed

Lines changed: 96 additions & 0 deletions

File tree

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
""" pyplots.ai
2+
andrews-curves: Andrews Curves for Multivariate Data
3+
Library: matplotlib 3.10.8 | Python 3.13.11
4+
Quality: 91/100 | Created: 2025-12-30
5+
"""
6+
7+
import matplotlib.pyplot as plt
8+
import numpy as np
9+
from sklearn.datasets import load_iris
10+
from sklearn.preprocessing import StandardScaler
11+
12+
13+
# Load and prepare data
14+
iris = load_iris()
15+
X = iris.data
16+
y = iris.target
17+
species_names = ["Setosa", "Versicolor", "Virginica"]
18+
19+
# Normalize data to prevent dominant variables
20+
scaler = StandardScaler()
21+
X_scaled = scaler.fit_transform(X)
22+
23+
# Generate t values from -π to π
24+
t = np.linspace(-np.pi, np.pi, 200)
25+
26+
# Build Andrews curve transformation matrix
27+
# f(t) = x1/sqrt(2) + x2*sin(t) + x3*cos(t) + x4*sin(2t) + ...
28+
n_features = X_scaled.shape[1]
29+
basis = np.zeros((len(t), n_features))
30+
basis[:, 0] = 1 / np.sqrt(2)
31+
for i in range(1, n_features):
32+
freq = (i + 1) // 2
33+
if i % 2 == 1:
34+
basis[:, i] = np.sin(freq * t)
35+
else:
36+
basis[:, i] = np.cos(freq * t)
37+
38+
# Compute all Andrews curves: each row of X_scaled dot basis.T gives one curve
39+
curves = X_scaled @ basis.T # shape: (150, 200)
40+
41+
# Create plot
42+
fig, ax = plt.subplots(figsize=(16, 9))
43+
44+
# Colors for each species (Python Blue, Python Yellow, and a complementary color)
45+
colors = ["#306998", "#FFD43B", "#E06C75"]
46+
47+
# Plot Andrews curves for each observation
48+
for i in range(len(curves)):
49+
ax.plot(t, curves[i], color=colors[y[i]], alpha=0.4, linewidth=1.5)
50+
51+
# Create legend with sample lines
52+
for idx, species in enumerate(species_names):
53+
ax.plot([], [], color=colors[idx], linewidth=3, label=species, alpha=0.8)
54+
55+
# Styling
56+
ax.set_xlabel("t (radians)", fontsize=20)
57+
ax.set_ylabel("f(t)", fontsize=20)
58+
ax.set_title("andrews-curves · matplotlib · pyplots.ai", fontsize=24)
59+
ax.tick_params(axis="both", labelsize=16)
60+
ax.legend(fontsize=16, loc="upper right")
61+
ax.grid(True, alpha=0.3, linestyle="--")
62+
63+
# Set x-axis ticks at meaningful positions
64+
ax.set_xticks([-np.pi, -np.pi / 2, 0, np.pi / 2, np.pi])
65+
ax.set_xticklabels(["-π", "-π/2", "0", "π/2", "π"], fontsize=16)
66+
67+
plt.tight_layout()
68+
plt.savefig("plot.png", dpi=300, bbox_inches="tight")
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
library: matplotlib
2+
specification_id: andrews-curves
3+
created: '2025-12-30T23:55:55Z'
4+
updated: '2025-12-31T00:02:02Z'
5+
generated_by: claude-opus-4-5-20251101
6+
workflow_run: 20608490813
7+
issue: 2859
8+
python_version: 3.13.11
9+
library_version: 3.10.8
10+
preview_url: https://storage.googleapis.com/pyplots-images/plots/andrews-curves/matplotlib/plot.png
11+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/andrews-curves/matplotlib/plot_thumb.png
12+
preview_html: null
13+
quality_score: 91
14+
review:
15+
strengths:
16+
- Excellent implementation of Andrews curves algorithm using Fourier basis functions
17+
- Clean visualization that clearly shows Setosa species separation from Versicolor/Virginica
18+
- Proper normalization with StandardScaler prevents dominant variables
19+
- Appropriate transparency (alpha=0.4) for 150 overlapping curves reveals density
20+
patterns
21+
- X-axis uses mathematically meaningful tick labels (-π, -π/2, 0, π/2, π)
22+
weaknesses:
23+
- Missing np.random.seed(42) in code (though Iris dataset is deterministic, best
24+
practice is to include it)
25+
- Linewidth=1.5 is slightly below recommended 2-4 for high-resolution plots per
26+
library guidelines
27+
- Legend sample lines use alpha=0.8 while actual curves use alpha=0.4, creating
28+
visual inconsistency

0 commit comments

Comments
 (0)