From 1c43ea712ada027d26e89f676f7014eb78f74f93 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 30 Dec 2025 23:54:38 +0000 Subject: [PATCH 1/3] feat(plotly): implement scatter-regression-lowess --- .../implementations/plotly.py | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 plots/scatter-regression-lowess/implementations/plotly.py diff --git a/plots/scatter-regression-lowess/implementations/plotly.py b/plots/scatter-regression-lowess/implementations/plotly.py new file mode 100644 index 0000000000..c4a142f6b3 --- /dev/null +++ b/plots/scatter-regression-lowess/implementations/plotly.py @@ -0,0 +1,116 @@ +"""pyplots.ai +scatter-regression-lowess: Scatter Plot with LOWESS Regression +Library: plotly | Python 3.13 +Quality: pending | Created: 2025-12-30 +""" + +import numpy as np +import plotly.graph_objects as go + + +# Data - Generate non-linear relationship with varying patterns +np.random.seed(42) +n_points = 200 +x = np.linspace(0, 10, n_points) +# Complex non-linear relationship: combination of sinusoidal and polynomial +y = 2 * np.sin(x) + 0.3 * x**2 - x + np.random.normal(0, 1.5, n_points) + +# LOWESS smoothing (Locally Weighted Scatterplot Smoothing) +frac = 0.3 +n = len(x) +k = int(np.ceil(frac * n)) # Number of neighbors to use + +# Sort data by x for processing +sorted_idx = np.argsort(x) +x_sorted = x[sorted_idx] +y_sorted = y[sorted_idx] +y_smooth = np.zeros(n) + +# Calculate smoothed values for each point +for i in range(n): + # Distances from current point to all points + distances = np.abs(x_sorted - x_sorted[i]) + + # Find k nearest neighbors + neighbor_idx = np.argsort(distances)[:k] + max_dist = distances[neighbor_idx[-1]] + + # Tricube weight function: w = (1 - (d/max_d)^3)^3 + if max_dist > 0: + u = distances[neighbor_idx] / max_dist + weights = (1 - u**3) ** 3 + else: + weights = np.ones(k) + + # Weighted least squares regression + x_neighbors = x_sorted[neighbor_idx] + y_neighbors = y_sorted[neighbor_idx] + + sum_w = np.sum(weights) + sum_wx = np.sum(weights * x_neighbors) + sum_wy = np.sum(weights * y_neighbors) + sum_wxx = np.sum(weights * x_neighbors**2) + sum_wxy = np.sum(weights * x_neighbors * y_neighbors) + + denom = sum_w * sum_wxx - sum_wx**2 + if np.abs(denom) > 1e-10: + b = (sum_w * sum_wxy - sum_wx * sum_wy) / denom + a = (sum_wy - b * sum_wx) / sum_w + y_smooth[i] = a + b * x_sorted[i] + else: + y_smooth[i] = sum_wy / sum_w if sum_w > 0 else y_sorted[i] + +x_lowess = x_sorted +y_lowess = y_smooth + +# Create figure +fig = go.Figure() + +# Add scatter points +fig.add_trace( + go.Scatter( + x=x, + y=y, + mode="markers", + name="Data Points", + marker=dict( + size=10, + color="#306998", # Python Blue + opacity=0.6, + ), + ) +) + +# Add LOWESS curve +fig.add_trace( + go.Scatter( + x=x_lowess, + y=y_lowess, + mode="lines", + name="LOWESS Curve", + line=dict( + color="#FFD43B", # Python Yellow + width=4, + ), + ) +) + +# Update layout for large canvas +fig.update_layout( + title=dict(text="scatter-regression-lowess · plotly · pyplots.ai", font=dict(size=28), x=0.5, xanchor="center"), + xaxis=dict( + title=dict(text="X Value", font=dict(size=22)), tickfont=dict(size=18), gridcolor="rgba(0,0,0,0.1)", gridwidth=1 + ), + yaxis=dict( + title=dict(text="Y Value", font=dict(size=22)), tickfont=dict(size=18), gridcolor="rgba(0,0,0,0.1)", gridwidth=1 + ), + template="plotly_white", + legend=dict(font=dict(size=18), x=0.02, y=0.98, xanchor="left", yanchor="top", bgcolor="rgba(255,255,255,0.8)"), + margin=dict(l=80, r=40, t=80, b=80), +) + +# Save as PNG (4800 x 2700 px) +fig.write_image("plot.png", width=1600, height=900, scale=3) + +# Save as HTML for interactivity +fig.write_html("plot.html") From 3efcbe544d7013918e60e8a398f66c67c8769d31 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 30 Dec 2025 23:54:52 +0000 Subject: [PATCH 2/3] chore(plotly): add metadata for scatter-regression-lowess --- .../metadata/plotly.yaml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 plots/scatter-regression-lowess/metadata/plotly.yaml diff --git a/plots/scatter-regression-lowess/metadata/plotly.yaml b/plots/scatter-regression-lowess/metadata/plotly.yaml new file mode 100644 index 0000000000..93ae30a81b --- /dev/null +++ b/plots/scatter-regression-lowess/metadata/plotly.yaml @@ -0,0 +1,19 @@ +# Per-library metadata for plotly implementation of scatter-regression-lowess +# Auto-generated by impl-generate.yml + +library: plotly +specification_id: scatter-regression-lowess +created: '2025-12-30T23:54:51Z' +updated: '2025-12-30T23:54:51Z' +generated_by: claude-opus-4-5-20251101 +workflow_run: 20608460845 +issue: 2855 +python_version: 3.13.11 +library_version: 6.5.0 +preview_url: https://storage.googleapis.com/pyplots-images/plots/scatter-regression-lowess/plotly/plot.png +preview_thumb: https://storage.googleapis.com/pyplots-images/plots/scatter-regression-lowess/plotly/plot_thumb.png +preview_html: https://storage.googleapis.com/pyplots-images/plots/scatter-regression-lowess/plotly/plot.html +quality_score: null +review: + strengths: [] + weaknesses: [] From 78bf73eed1b5da61ceba684c65932927be6362ed Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 31 Dec 2025 00:01:00 +0000 Subject: [PATCH 3/3] chore(plotly): update quality score 91 and review feedback for scatter-regression-lowess --- .../implementations/plotly.py | 6 ++--- .../metadata/plotly.yaml | 22 +++++++++++++------ 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/plots/scatter-regression-lowess/implementations/plotly.py b/plots/scatter-regression-lowess/implementations/plotly.py index c4a142f6b3..5467ae9927 100644 --- a/plots/scatter-regression-lowess/implementations/plotly.py +++ b/plots/scatter-regression-lowess/implementations/plotly.py @@ -1,7 +1,7 @@ -"""pyplots.ai +""" pyplots.ai scatter-regression-lowess: Scatter Plot with LOWESS Regression -Library: plotly | Python 3.13 -Quality: pending | Created: 2025-12-30 +Library: plotly 6.5.0 | Python 3.13.11 +Quality: 91/100 | Created: 2025-12-30 """ import numpy as np diff --git a/plots/scatter-regression-lowess/metadata/plotly.yaml b/plots/scatter-regression-lowess/metadata/plotly.yaml index 93ae30a81b..1ef499c4e4 100644 --- a/plots/scatter-regression-lowess/metadata/plotly.yaml +++ b/plots/scatter-regression-lowess/metadata/plotly.yaml @@ -1,10 +1,7 @@ -# Per-library metadata for plotly implementation of scatter-regression-lowess -# Auto-generated by impl-generate.yml - library: plotly specification_id: scatter-regression-lowess created: '2025-12-30T23:54:51Z' -updated: '2025-12-30T23:54:51Z' +updated: '2025-12-31T00:01:00Z' generated_by: claude-opus-4-5-20251101 workflow_run: 20608460845 issue: 2855 @@ -13,7 +10,18 @@ library_version: 6.5.0 preview_url: https://storage.googleapis.com/pyplots-images/plots/scatter-regression-lowess/plotly/plot.png preview_thumb: https://storage.googleapis.com/pyplots-images/plots/scatter-regression-lowess/plotly/plot_thumb.png preview_html: https://storage.googleapis.com/pyplots-images/plots/scatter-regression-lowess/plotly/plot.html -quality_score: null +quality_score: 91 review: - strengths: [] - weaknesses: [] + strengths: + - Excellent implementation of LOWESS algorithm from scratch with proper tricube + weighting + - Clear visual distinction between scatter points (blue, transparent) and LOWESS + curve (yellow, solid line) + - Perfect title format and professional plotly_white template + - Good font sizes throughout ensuring readability at 4800x2700 resolution + - Well-chosen smoothing fraction (0.3) that captures the trend without overfitting + weaknesses: + - Axis labels lack units or more descriptive context (e.g., could use domain-specific + labels) + - Manual LOWESS implementation is educational but verbose; could leverage statsmodels + for production code