Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions plots/scatter-size-mapped/implementations/pygal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
""" pyplots.ai
scatter-size-mapped: Bubble Chart
Library: pygal 3.1.0 | Python 3.13.11
Quality: 91/100 | Created: 2025-12-27
"""

import numpy as np
import pygal
from pygal.style import Style


# Data: Country economic indicators
np.random.seed(42)

# Generate 40 synthetic countries across different regions
n_countries = 40
regions = ["Europe", "Asia", "Americas", "Africa"]

# Assign regions with some variation
region_assignments = np.random.choice(regions, n_countries)

# GDP per capita (1,000 - 80,000)
gdp_per_capita = np.random.uniform(5000, 75000, n_countries)
# Adjust by region for realism
for i, region in enumerate(region_assignments):
if region == "Europe":
gdp_per_capita[i] = np.random.uniform(25000, 75000)
elif region == "Asia":
gdp_per_capita[i] = np.random.uniform(5000, 60000)
elif region == "Americas":
gdp_per_capita[i] = np.random.uniform(8000, 70000)
else: # Africa
gdp_per_capita[i] = np.random.uniform(1000, 20000)

# Life expectancy (50-85) correlated with GDP
life_expectancy = 50 + 30 * (gdp_per_capita / 80000) + np.random.uniform(-5, 5, n_countries)
life_expectancy = np.clip(life_expectancy, 50, 85)

# Population (log scale, 1M - 1.4B)
population = 10 ** np.random.uniform(6, 9.2, n_countries)

# Create custom style with larger font sizes for better rendering
custom_style = Style(
background="white",
plot_background="white",
foreground="#333333",
foreground_strong="#333333",
foreground_subtle="#666666",
colors=("#306998", "#FFD43B", "#E74C3C", "#27AE60", "#9B59B6"),
title_font_size=84,
label_font_size=56,
major_label_font_size=48,
legend_font_size=44,
value_font_size=40,
opacity=0.6,
opacity_hover=0.8,
)

# Title with size legend information
title = "scatter-size-mapped · pygal · pyplots.ai\nBubble Size = Population (1M to 1B+)"

# Create XY chart for scatter plot
chart = pygal.XY(
width=4800,
height=2700,
style=custom_style,
title=title,
x_title="GDP per Capita (USD)",
y_title="Life Expectancy (years)",
show_legend=True,
legend_at_bottom=True,
legend_at_bottom_columns=4,
dots_size=15,
show_x_guides=True,
show_y_guides=True,
stroke=False,
explicit_size=True,
truncate_legend=-1,
)

# Group data by region and add as series
# Pygal XY chart uses value dict with 'value' for coordinates
for region in regions:
mask = region_assignments == region
points = []
for i in np.where(mask)[0]:
# Scale population to reasonable dot size (log scale)
# Population ranges from 1M to 1.4B, scale to 12-70 for better visibility
# Increased minimum size from 5 to 12 so smaller bubbles are visible
size = 12 + 58 * (np.log10(population[i]) - 6) / 3.2
points.append({"value": (float(gdp_per_capita[i]), float(life_expectancy[i])), "node": {"r": size}})
chart.add(region, points)

# Render to files
chart.render_to_png("plot.png")
chart.render_to_file("plot.html")
29 changes: 29 additions & 0 deletions plots/scatter-size-mapped/metadata/pygal.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
library: pygal
specification_id: scatter-size-mapped
created: '2025-12-27T19:31:03Z'
updated: '2025-12-27T19:43:26Z'
generated_by: claude-opus-4-5-20251101
workflow_run: 20543371845
issue: 0
python_version: 3.13.11
library_version: 3.1.0
preview_url: https://storage.googleapis.com/pyplots-images/plots/scatter-size-mapped/pygal/plot.png
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/scatter-size-mapped/pygal/plot_thumb.png
preview_html: https://storage.googleapis.com/pyplots-images/plots/scatter-size-mapped/pygal/plot.html
quality_score: 91
review:
strengths:
- Excellent realistic data generation with regional economic patterns (Europe higher
GDP, Africa lower GDP)
- Proper use of pygal XY chart with custom node sizes via the node dict parameter
for bubble sizing
- Well-implemented semi-transparency (opacity=0.6) for distinguishing overlapping
bubbles
- Clean code structure following KISS principles with proper seed for reproducibility
- Size legend integrated into title subtitle (Bubble Size = Population 1M to 1B+)
- Improved minimum bubble size (12) from previous attempt makes smaller populations
more visible
weaknesses:
- Grid lines are too subtle and barely visible - could use more prominent guide
styling
- Title format includes subtitle which slightly deviates from the exact spec format