From 3ec7b07f3badaa75d1d0094eb5e33ec3f383c2b3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 26 Dec 2025 19:35:40 +0000 Subject: [PATCH 1/3] feat(altair): implement residual-plot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- plots/residual-plot/implementations/altair.py | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 plots/residual-plot/implementations/altair.py diff --git a/plots/residual-plot/implementations/altair.py b/plots/residual-plot/implementations/altair.py new file mode 100644 index 0000000000..d93d12dbfb --- /dev/null +++ b/plots/residual-plot/implementations/altair.py @@ -0,0 +1,89 @@ +"""pyplots.ai +residual-plot: Residual Plot +Library: altair | Python 3.13 +Quality: pending | Created: 2025-12-26 +""" + +import altair as alt +import numpy as np +import pandas as pd + + +# Data: Simulate a linear regression scenario with some non-linearity +np.random.seed(42) +n = 150 + +# Generate realistic housing price prediction scenario +x = np.linspace(1000, 3000, n) # House size in sq ft +noise = np.random.randn(n) * 15000 +y_true = 50000 + 150 * x + 0.02 * (x - 2000) ** 2 + noise # True prices with slight curvature +y_pred = 50000 + 155 * x # Linear model predictions + +residuals = y_true - y_pred +std_residual = np.std(residuals) + +# Identify outliers (beyond ±2 standard deviations) +is_outlier = np.abs(residuals) > 2 * std_residual + +# Create DataFrame +df = pd.DataFrame( + { + "Fitted Values ($)": y_pred, + "Residuals ($)": residuals, + "Outlier": np.where(is_outlier, "Outlier (>2σ)", "Normal"), + } +) + +# Base scatter plot with color encoding for outliers +scatter = ( + alt.Chart(df) + .mark_point(size=120, opacity=0.7) + .encode( + x=alt.X("Fitted Values ($):Q", title="Fitted Values ($)", scale=alt.Scale(nice=True)), + y=alt.Y("Residuals ($):Q", title="Residuals ($)", scale=alt.Scale(nice=True)), + color=alt.Color( + "Outlier:N", + scale=alt.Scale(domain=["Normal", "Outlier (>2σ)"], range=["#306998", "#FFD43B"]), + legend=alt.Legend(title="Point Type", titleFontSize=18, labelFontSize=16), + ), + tooltip=["Fitted Values ($):Q", "Residuals ($):Q", "Outlier:N"], + ) +) + +# Zero reference line +zero_line = ( + alt.Chart(pd.DataFrame({"y": [0]})).mark_rule(color="#333333", strokeWidth=2, strokeDash=[8, 4]).encode(y="y:Q") +) + +# ±2 standard deviation bands +bands_df = pd.DataFrame({"y": [2 * std_residual, -2 * std_residual], "label": ["+2σ", "-2σ"]}) + +band_lines = alt.Chart(bands_df).mark_rule(color="#888888", strokeWidth=1.5, strokeDash=[4, 4]).encode(y="y:Q") + +# Add LOWESS-like trend using polynomial regression +loess_df = df.copy() +loess_df = loess_df.sort_values("Fitted Values ($)") + +loess_line = ( + alt.Chart(loess_df) + .transform_loess("Fitted Values ($)", "Residuals ($)", bandwidth=0.3) + .mark_line(color="#E24A33", strokeWidth=3) + .encode(x="Fitted Values ($):Q", y="Residuals ($):Q") +) + +# Combine all layers +chart = ( + alt.layer(zero_line, band_lines, scatter, loess_line) + .properties( + width=1600, + height=900, + title=alt.Title(text="residual-plot · altair · pyplots.ai", fontSize=28, anchor="middle"), + ) + .configure_axis(labelFontSize=18, titleFontSize=22, gridOpacity=0.3) + .configure_view(strokeWidth=0) + .configure_legend(orient="right", padding=10) +) + +# Save outputs +chart.save("plot.png", scale_factor=3.0) +chart.save("plot.html") From 795fa88449fb5177298c922f04947b9eec7e9a96 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 26 Dec 2025 19:35:59 +0000 Subject: [PATCH 2/3] chore(altair): add metadata for residual-plot --- plots/residual-plot/metadata/altair.yaml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 plots/residual-plot/metadata/altair.yaml diff --git a/plots/residual-plot/metadata/altair.yaml b/plots/residual-plot/metadata/altair.yaml new file mode 100644 index 0000000000..7d0c14a5bf --- /dev/null +++ b/plots/residual-plot/metadata/altair.yaml @@ -0,0 +1,19 @@ +# Per-library metadata for altair implementation of residual-plot +# Auto-generated by impl-generate.yml + +library: altair +specification_id: residual-plot +created: '2025-12-26T19:35:59Z' +updated: '2025-12-26T19:35:59Z' +generated_by: claude-opus-4-5-20251101 +workflow_run: 20528204950 +issue: 0 +python_version: 3.13.11 +library_version: 6.0.0 +preview_url: https://storage.googleapis.com/pyplots-images/plots/residual-plot/altair/plot.png +preview_thumb: https://storage.googleapis.com/pyplots-images/plots/residual-plot/altair/plot_thumb.png +preview_html: https://storage.googleapis.com/pyplots-images/plots/residual-plot/altair/plot.html +quality_score: null +review: + strengths: [] + weaknesses: [] From 97e9fd9a1a9044b372828004144a33ced17ede75 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 26 Dec 2025 19:41:11 +0000 Subject: [PATCH 3/3] chore(altair): update quality score 91 and review feedback for residual-plot --- plots/residual-plot/implementations/altair.py | 6 ++--- plots/residual-plot/metadata/altair.yaml | 24 +++++++++++++------ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/plots/residual-plot/implementations/altair.py b/plots/residual-plot/implementations/altair.py index d93d12dbfb..b0e1985454 100644 --- a/plots/residual-plot/implementations/altair.py +++ b/plots/residual-plot/implementations/altair.py @@ -1,7 +1,7 @@ -"""pyplots.ai +""" pyplots.ai residual-plot: Residual Plot -Library: altair | Python 3.13 -Quality: pending | Created: 2025-12-26 +Library: altair 6.0.0 | Python 3.13.11 +Quality: 91/100 | Created: 2025-12-26 """ import altair as alt diff --git a/plots/residual-plot/metadata/altair.yaml b/plots/residual-plot/metadata/altair.yaml index 7d0c14a5bf..088af3dbf0 100644 --- a/plots/residual-plot/metadata/altair.yaml +++ b/plots/residual-plot/metadata/altair.yaml @@ -1,10 +1,7 @@ -# Per-library metadata for altair implementation of residual-plot -# Auto-generated by impl-generate.yml - library: altair specification_id: residual-plot created: '2025-12-26T19:35:59Z' -updated: '2025-12-26T19:35:59Z' +updated: '2025-12-26T19:41:11Z' generated_by: claude-opus-4-5-20251101 workflow_run: 20528204950 issue: 0 @@ -13,7 +10,20 @@ library_version: 6.0.0 preview_url: https://storage.googleapis.com/pyplots-images/plots/residual-plot/altair/plot.png preview_thumb: https://storage.googleapis.com/pyplots-images/plots/residual-plot/altair/plot_thumb.png preview_html: https://storage.googleapis.com/pyplots-images/plots/residual-plot/altair/plot.html -quality_score: null +quality_score: 91 review: - strengths: [] - weaknesses: [] + strengths: + - Excellent implementation of all specification requirements including zero reference + line, LOESS smoothing, ±2σ bands, and outlier highlighting + - Clear demonstration of non-linear residual pattern through LOESS line - educationally + valuable + - Strong colorblind-safe palette with Python logo colors (blue/yellow) + - Good use of Altair declarative layering for combining multiple visual elements + - Realistic housing price scenario makes the plot immediately comprehensible + - Proper title format and descriptive axis labels with units + weaknesses: + - Legend placement is slightly isolated from the main chart area - could be positioned + closer + - Points use outlined circles which can be slightly less visible than filled circles + at smaller sizes + - The grid lines behind the ±2σ dashed lines create slight visual noise