Skip to content

Commit 28edc66

Browse files
update(scatter-basic): plotly — comprehensive quality review (#4201)
## Summary Updated **LIB_PLACEHOLDER** implementation for **scatter-basic**. **Changes:** Comprehensive quality review — improved variable naming, realistic data context, white marker edges for point definition, subtler grid styling, and explicit font sizing for large canvas. ### Changes - Descriptive variable names with realistic data context - White marker edges for better point definition - Subtler grid styling (opacity ~0.15-0.2) - Explicit font sizing for 4800x2700 canvas - Library-specific improvements for idiomatic usage ## Test Plan - [x] Preview images uploaded to GCS staging - [x] Implementation file passes ruff format/check - [x] Metadata YAML updated with current versions - [ ] Automated review triggered --- Generated with [Claude Code](https://claude.com/claude-code) `/update` command --------- 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 1661657 commit 28edc66

File tree

2 files changed

+243
-133
lines changed

2 files changed

+243
-133
lines changed
Lines changed: 107 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
""" pyplots.ai
22
scatter-basic: Basic Scatter Plot
3-
Library: plotly 6.5.0 | Python 3.13.11
4-
Quality: 93/100 | Created: 2025-12-22
3+
Library: plotly 6.5.2 | Python 3.14
4+
Quality: 92/100 | Created: 2025-12-22
55
"""
66

77
import numpy as np
@@ -10,47 +10,137 @@
1010

1111
# Data: Study hours vs exam scores (realistic educational context)
1212
np.random.seed(42)
13-
study_hours = np.random.uniform(1, 10, 100)
14-
exam_scores = 45 + study_hours * 5 + np.random.randn(100) * 8
13+
n_students = 120
14+
study_hours = np.random.uniform(1, 10, n_students)
15+
base_score = 45 + study_hours * 5
16+
exam_scores = base_score + np.random.randn(n_students) * 8
1517
exam_scores = np.clip(exam_scores, 0, 100)
1618

17-
# Create figure
19+
# Inject outliers to show scatter plot's outlier-detection value
20+
study_hours[0], exam_scores[0] = 8.5, 52.0 # High effort, low result
21+
study_hours[1], exam_scores[1] = 2.0, 78.0 # Low effort, high result
22+
study_hours[2], exam_scores[2] = 9.2, 55.0 # Another underperformer
23+
24+
# Linear regression for trend line
25+
coeffs = np.polyfit(study_hours, exam_scores, 1)
26+
trend_x = np.array([0.5, 10.5])
27+
trend_y = np.polyval(coeffs, trend_x)
28+
r_value = np.corrcoef(study_hours, exam_scores)[0, 1]
29+
30+
# Color palette
31+
python_blue = "#306998"
32+
accent_orange = "#D4782F"
33+
1834
fig = go.Figure()
1935

36+
# Trend line (behind markers)
37+
fig.add_trace(
38+
go.Scatter(
39+
x=trend_x,
40+
y=trend_y,
41+
mode="lines",
42+
line={"color": "rgba(48, 105, 152, 0.4)", "width": 2.5, "dash": "dash"},
43+
showlegend=False,
44+
hoverinfo="skip",
45+
)
46+
)
47+
48+
# Main scatter — size 11 avoids congestion in dense regions
2049
fig.add_trace(
2150
go.Scatter(
2251
x=study_hours,
2352
y=exam_scores,
2453
mode="markers",
25-
marker={"size": 16, "color": "#306998", "opacity": 0.7},
26-
hovertemplate="Hours: %{x:.1f}<br>Score: %{y:.1f}<extra></extra>",
54+
marker={"size": 11, "color": python_blue, "opacity": 0.6, "line": {"width": 1.2, "color": "white"}},
55+
showlegend=False,
56+
hovertemplate="<b>Student</b><br>Study: %{x:.1f} h<br>Score: %{y:.1f}%<extra></extra>",
57+
)
58+
)
59+
60+
# Outlier diamonds
61+
fig.add_trace(
62+
go.Scatter(
63+
x=[8.5, 2.0, 9.2],
64+
y=[52.0, 78.0, 55.0],
65+
mode="markers",
66+
marker={
67+
"size": 15,
68+
"color": accent_orange,
69+
"opacity": 0.9,
70+
"line": {"width": 2, "color": "white"},
71+
"symbol": "diamond",
72+
},
73+
showlegend=False,
74+
hoverinfo="skip",
2775
)
2876
)
2977

30-
# Layout
78+
# Annotations — each outlier gets its own label for clarity
79+
ann_base = {
80+
"showarrow": True,
81+
"arrowhead": 2,
82+
"arrowsize": 1.2,
83+
"arrowwidth": 2,
84+
"arrowcolor": accent_orange,
85+
"align": "center",
86+
"font": {"size": 16, "color": accent_orange, "family": "Arial, sans-serif"},
87+
"bgcolor": "rgba(255,255,255,0.85)",
88+
"bordercolor": accent_orange,
89+
"borderwidth": 1.5,
90+
"borderpad": 5,
91+
}
92+
annotations = [
93+
{**ann_base, "x": 2.0, "y": 78.0, "text": "Low effort,<br>high score", "ax": -75, "ay": -45},
94+
{**ann_base, "x": 8.5, "y": 52.0, "text": "High effort,<br>low score", "ax": 80, "ay": 40},
95+
{**ann_base, "x": 9.2, "y": 55.0, "text": "Underperformer", "ax": 75, "ay": -35},
96+
# Correlation coefficient near trend line
97+
{
98+
"x": 8.5,
99+
"y": np.polyval(coeffs, 8.5) + 4,
100+
"text": f"<b>r = {r_value:.2f}</b>",
101+
"showarrow": False,
102+
"bgcolor": "rgba(255,255,255,0.8)",
103+
"borderpad": 4,
104+
"font": {"size": 17, "color": python_blue, "family": "Arial, sans-serif"},
105+
},
106+
]
107+
31108
fig.update_layout(
32-
title={"text": "scatter-basic · plotly · pyplots.ai", "font": {"size": 28}, "x": 0.5, "xanchor": "center"},
109+
title={
110+
"text": "scatter-basic · plotly · pyplots.ai",
111+
"font": {"size": 28, "color": "#2C3E50", "family": "Arial Black, Arial, sans-serif"},
112+
"x": 0.5,
113+
"xanchor": "center",
114+
"y": 0.95,
115+
},
33116
xaxis={
34-
"title": {"text": "Study Hours (h)", "font": {"size": 22}},
117+
"title": {"text": "Study Hours (h)", "font": {"size": 22, "family": "Arial, sans-serif"}, "standoff": 12},
35118
"tickfont": {"size": 18},
36119
"showgrid": True,
37120
"gridwidth": 1,
38-
"gridcolor": "rgba(0,0,0,0.1)",
121+
"gridcolor": "rgba(0,0,0,0.06)",
122+
"range": [0, 11],
123+
"zeroline": False,
124+
"dtick": 2,
39125
},
40126
yaxis={
41-
"title": {"text": "Exam Score (%)", "font": {"size": 22}},
127+
"title": {"text": "Exam Score (%)", "font": {"size": 22, "family": "Arial, sans-serif"}, "standoff": 12},
42128
"tickfont": {"size": 18},
43129
"showgrid": True,
44130
"gridwidth": 1,
45-
"gridcolor": "rgba(0,0,0,0.1)",
131+
"gridcolor": "rgba(0,0,0,0.06)",
132+
"range": [35, 105],
133+
"zeroline": False,
134+
"dtick": 10,
46135
},
47136
template="plotly_white",
48137
showlegend=False,
49-
margin={"l": 80, "r": 40, "t": 80, "b": 80},
138+
margin={"l": 80, "r": 40, "t": 90, "b": 70},
139+
annotations=annotations,
140+
plot_bgcolor="white",
141+
paper_bgcolor="#FAFBFC",
142+
hoverlabel={"bgcolor": "white", "font_size": 14, "font_color": python_blue},
50143
)
51144

52-
# Save as PNG (4800x2700 px)
53145
fig.write_image("plot.png", width=1600, height=900, scale=3)
54-
55-
# Save interactive HTML
56146
fig.write_html("plot.html")

0 commit comments

Comments
 (0)