Skip to content

Commit 9e479ca

Browse files
feat(plotly): implement scatter-annotated (#2818)
## Implementation: `scatter-annotated` - plotly Implements the **plotly** version of `scatter-annotated`. **File:** `plots/scatter-annotated/implementations/plotly.py` --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/20602450204)* --------- 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 3283c66 commit 9e479ca

2 files changed

Lines changed: 158 additions & 0 deletions

File tree

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
""" pyplots.ai
2+
scatter-annotated: Annotated Scatter Plot with Text Labels
3+
Library: plotly 6.5.0 | Python 3.13.11
4+
Quality: 92/100 | Created: 2025-12-30
5+
"""
6+
7+
import numpy as np
8+
import plotly.graph_objects as go
9+
10+
11+
# Data - Top tech companies by market cap and revenue (12 companies for cleaner annotations)
12+
np.random.seed(42)
13+
14+
companies = [
15+
"Apple",
16+
"Microsoft",
17+
"Alphabet",
18+
"Amazon",
19+
"Meta",
20+
"Tesla",
21+
"Nvidia",
22+
"Samsung",
23+
"TSMC",
24+
"Oracle",
25+
"Salesforce",
26+
"Netflix",
27+
]
28+
29+
# Market cap (billions USD) - x axis
30+
market_cap = np.array([2800, 2700, 1700, 1500, 900, 700, 1200, 350, 500, 300, 250, 250])
31+
32+
# Annual revenue (billions USD) - y axis
33+
revenue = np.array([380, 210, 280, 520, 130, 95, 60, 230, 70, 50, 32, 33])
34+
35+
# Create figure
36+
fig = go.Figure()
37+
38+
# Add scatter points
39+
fig.add_trace(
40+
go.Scatter(
41+
x=market_cap,
42+
y=revenue,
43+
mode="markers+text",
44+
marker=dict(size=20, color="#306998", opacity=0.7, line=dict(width=2, color="white")),
45+
text=companies,
46+
textposition="top center",
47+
textfont=dict(size=14, color="#333333"),
48+
hovertemplate="<b>%{text}</b><br>Market Cap: $%{x}B<br>Revenue: $%{y}B<extra></extra>",
49+
)
50+
)
51+
52+
# Manually adjust label positions to avoid overlap
53+
annotations = []
54+
55+
# Position adjustments (ax, ay in pixels from point)
56+
position_adjustments = {
57+
"Apple": (70, -45),
58+
"Microsoft": (-90, 45),
59+
"Alphabet": (80, 0),
60+
"Amazon": (0, -55),
61+
"Nvidia": (0, 55),
62+
"TSMC": (75, 20),
63+
"Meta": (70, -35),
64+
"Tesla": (-75, -25),
65+
"Samsung": (-80, 0),
66+
"Oracle": (75, -30),
67+
"Salesforce": (-90, 0),
68+
"Netflix": (80, 25),
69+
}
70+
71+
# Remove default text labels and add custom annotations with arrows
72+
fig.update_traces(mode="markers", textposition=None, text=None)
73+
74+
for company, cap, rev in zip(companies, market_cap, revenue):
75+
ax, ay = position_adjustments.get(company, (0, -40))
76+
77+
annotations.append(
78+
dict(
79+
x=cap,
80+
y=rev,
81+
text=f"<b>{company}</b>",
82+
showarrow=True,
83+
arrowhead=2,
84+
arrowsize=1,
85+
arrowwidth=2,
86+
arrowcolor="#306998",
87+
ax=ax,
88+
ay=ay,
89+
font=dict(size=18, color="#333333"),
90+
bgcolor="rgba(255,255,255,0.9)",
91+
bordercolor="#306998",
92+
borderwidth=1,
93+
borderpad=4,
94+
)
95+
)
96+
97+
# Update layout
98+
fig.update_layout(
99+
title=dict(
100+
text="scatter-annotated · plotly · pyplots.ai", font=dict(size=32, color="#333333"), x=0.5, xanchor="center"
101+
),
102+
xaxis=dict(
103+
title=dict(text="Market Cap (Billion USD)", font=dict(size=24)),
104+
tickfont=dict(size=18),
105+
gridcolor="rgba(0,0,0,0.1)",
106+
gridwidth=1,
107+
showline=True,
108+
linewidth=2,
109+
linecolor="#333333",
110+
range=[-100, 3100],
111+
),
112+
yaxis=dict(
113+
title=dict(text="Annual Revenue (Billion USD)", font=dict(size=24)),
114+
tickfont=dict(size=18),
115+
gridcolor="rgba(0,0,0,0.1)",
116+
gridwidth=1,
117+
showline=True,
118+
linewidth=2,
119+
linecolor="#333333",
120+
range=[-30, 580],
121+
),
122+
template="plotly_white",
123+
annotations=annotations,
124+
margin=dict(l=100, r=80, t=100, b=100),
125+
showlegend=False,
126+
)
127+
128+
# Save as PNG (4800 x 2700 px)
129+
fig.write_image("plot.png", width=1600, height=900, scale=3)
130+
131+
# Save as HTML for interactivity
132+
fig.write_html("plot.html", include_plotlyjs=True)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
library: plotly
2+
specification_id: scatter-annotated
3+
created: '2025-12-30T17:49:25Z'
4+
updated: '2025-12-30T17:58:56Z'
5+
generated_by: claude-opus-4-5-20251101
6+
workflow_run: 20602450204
7+
issue: 0
8+
python_version: 3.13.11
9+
library_version: 6.5.0
10+
preview_url: https://storage.googleapis.com/pyplots-images/plots/scatter-annotated/plotly/plot.png
11+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/scatter-annotated/plotly/plot_thumb.png
12+
preview_html: https://storage.googleapis.com/pyplots-images/plots/scatter-annotated/plotly/plot.html
13+
quality_score: 92
14+
review:
15+
strengths:
16+
- Excellent manual annotation positioning with custom offsets for each company prevents
17+
label overlap
18+
- Clean annotation styling with white background boxes, blue borders, and connecting
19+
arrows
20+
- Good use of realistic tech company data that makes the plot immediately comprehensible
21+
- Proper title format and descriptive axis labels with units
22+
- Both PNG and HTML exports provided
23+
weaknesses:
24+
- Does not fully leverage plotly interactive capabilities as a distinctive feature
25+
(hover is secondary to static annotations)
26+
- Grid opacity (0.1) is too subtle and could be slightly more visible (0.2-0.3 recommended)

0 commit comments

Comments
 (0)