From de5d2c1a976f519a5ea24ddc9a6f5280b0c7b233 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 10 Jan 2026 06:09:35 +0000 Subject: [PATCH 1/3] feat(plotnine): implement bubble-map-geographic Co-Authored-By: Claude Opus 4.5 --- .../implementations/plotnine.py | 308 ++++++++++++++++++ 1 file changed, 308 insertions(+) create mode 100644 plots/bubble-map-geographic/implementations/plotnine.py diff --git a/plots/bubble-map-geographic/implementations/plotnine.py b/plots/bubble-map-geographic/implementations/plotnine.py new file mode 100644 index 0000000000..b040b77d53 --- /dev/null +++ b/plots/bubble-map-geographic/implementations/plotnine.py @@ -0,0 +1,308 @@ +"""pyplots.ai +bubble-map-geographic: Bubble Map with Sized Geographic Markers +Library: plotnine | Python 3.13 +Quality: pending | Created: 2026-01-10 +""" + +import numpy as np +import pandas as pd +from plotnine import ( + aes, + coord_fixed, + element_blank, + element_line, + element_rect, + element_text, + geom_point, + geom_polygon, + ggplot, + labs, + scale_color_manual, + scale_size_area, + theme, + theme_minimal, +) + + +# Seed for reproducibility +np.random.seed(42) + +# Major world cities with population data (in millions) +cities_data = { + "city": [ + "Tokyo", + "Delhi", + "Shanghai", + "Sao Paulo", + "Mexico City", + "Cairo", + "Mumbai", + "Beijing", + "Dhaka", + "Osaka", + "New York", + "Karachi", + "Buenos Aires", + "Istanbul", + "Kolkata", + "Lagos", + "Rio de Janeiro", + "Los Angeles", + "Moscow", + "Paris", + "Bangkok", + "Seoul", + "London", + "Lima", + "Chicago", + "Santiago", + "Sydney", + "Toronto", + "Singapore", + "Dubai", + ], + "latitude": [ + 35.68, + 28.61, + 31.23, + -23.55, + 19.43, + 30.04, + 19.08, + 39.90, + 23.81, + 34.69, + 40.71, + 24.86, + -34.60, + 41.01, + 22.57, + 6.52, + -22.91, + 34.05, + 55.76, + 48.86, + 13.76, + 37.57, + 51.51, + -12.05, + 41.88, + -33.45, + -33.87, + 43.65, + 1.35, + 25.20, + ], + "longitude": [ + 139.69, + 77.21, + 121.47, + -46.63, + -99.13, + 31.24, + 72.88, + 116.41, + 90.41, + 135.50, + -74.01, + 67.01, + -58.38, + 28.98, + 88.36, + 3.38, + -43.17, + -118.24, + 37.62, + 2.35, + 100.50, + 127.00, + -0.13, + -77.04, + -87.63, + -70.67, + 151.21, + -79.38, + 103.82, + 55.27, + ], + "population": [ + 37.4, + 32.9, + 29.2, + 22.4, + 21.8, + 21.3, + 21.0, + 20.9, + 22.5, + 19.1, + 18.8, + 16.8, + 15.4, + 15.6, + 15.1, + 15.3, + 13.5, + 12.5, + 12.5, + 11.0, + 10.7, + 9.9, + 9.5, + 11.0, + 8.9, + 6.8, + 5.3, + 6.3, + 5.9, + 3.4, + ], + "region": [ + "Asia", + "Asia", + "Asia", + "S. America", + "N. America", + "Africa", + "Asia", + "Asia", + "Asia", + "Asia", + "N. America", + "Asia", + "S. America", + "Europe", + "Asia", + "Africa", + "S. America", + "N. America", + "Europe", + "Europe", + "Asia", + "Asia", + "Europe", + "S. America", + "N. America", + "S. America", + "Oceania", + "N. America", + "Asia", + "Asia", + ], +} + +df = pd.DataFrame(cities_data) + +# Simplified continent outlines for basemap +continents = [] + +# North America +na_lon = [ + -170, + -168, + -140, + -125, + -124, + -117, + -105, + -97, + -82, + -77, + -68, + -55, + -52, + -80, + -87, + -97, + -105, + -125, + -145, + -165, + -170, +] +na_lat = [60, 65, 70, 55, 48, 33, 25, 26, 25, 35, 45, 48, 45, 27, 30, 20, 22, 50, 60, 55, 60] +for i in range(len(na_lon)): + continents.append({"continent": "N. America", "order": i, "lon": na_lon[i], "lat": na_lat[i]}) + +# South America +sa_lon = [-80, -68, -60, -50, -35, -40, -50, -55, -68, -72, -75, -80, -82, -80] +sa_lat = [10, 12, 5, 0, -5, -22, -35, -52, -55, -18, -5, 0, 8, 10] +for i in range(len(sa_lon)): + continents.append({"continent": "S. America", "order": i, "lon": sa_lon[i], "lat": sa_lat[i]}) + +# Europe +eu_lon = [-10, 0, 10, 20, 30, 40, 50, 60, 50, 35, 25, 20, 10, 0, -10, -10] +eu_lat = [35, 37, 36, 35, 35, 40, 45, 55, 70, 70, 70, 65, 60, 50, 40, 35] +for i in range(len(eu_lon)): + continents.append({"continent": "Europe", "order": i, "lon": eu_lon[i], "lat": eu_lat[i]}) + +# Africa +af_lon = [-17, -5, 10, 35, 50, 52, 43, 35, 30, 15, 0, -17, -17] +af_lat = [15, 37, 37, 32, 12, 0, -25, -35, -35, -25, 5, 20, 15] +for i in range(len(af_lon)): + continents.append({"continent": "Africa", "order": i, "lon": af_lon[i], "lat": af_lat[i]}) + +# Asia +as_lon = [60, 80, 100, 120, 140, 145, 140, 130, 105, 100, 80, 60, 45, 30, 25, 30, 35, 50, 60] +as_lat = [55, 70, 75, 70, 55, 45, 35, 30, 0, 5, 10, 25, 30, 35, 42, 55, 70, 70, 55] +for i in range(len(as_lon)): + continents.append({"continent": "Asia", "order": i, "lon": as_lon[i], "lat": as_lat[i]}) + +# Australia +au_lon = [113, 125, 135, 145, 152, 150, 140, 130, 115, 113] +au_lat = [-22, -15, -12, -15, -25, -38, -38, -33, -35, -22] +for i in range(len(au_lon)): + continents.append({"continent": "Australia", "order": i, "lon": au_lon[i], "lat": au_lat[i]}) + +df_continents = pd.DataFrame(continents) + +# Region color palette (colorblind-safe, alphabetically ordered for plotnine) +region_colors = [ + "#9467BD", # Africa - Purple + "#306998", # Asia - Python Blue + "#FFD43B", # Europe - Python Yellow + "#2CA02C", # N. America - Green + "#17BECF", # Oceania - Cyan + "#D62728", # S. America - Red +] + +# Create the bubble map +plot = ( + ggplot() + # Draw continent polygons as basemap + + geom_polygon( + aes(x="lon", y="lat", group="continent"), + data=df_continents, + fill="#E0E0E0", + color="#A0A0A0", + size=0.5, + alpha=0.8, + ) + # Draw bubble markers sized by population + + geom_point(aes(x="longitude", y="latitude", color="region", size="population"), data=df, alpha=0.7, stroke=0.5) + # Scale size by area for accurate perception (bubble area proportional to value) + + scale_size_area(max_size=20, name="Population (M)") + + scale_color_manual(values=region_colors, name="Region") + + coord_fixed(ratio=1.0, xlim=(-180, 180), ylim=(-60, 80)) + + labs( + title="World City Populations · bubble-map-geographic · plotnine · pyplots.ai", + x="Longitude (°)", + y="Latitude (°)", + ) + + theme_minimal() + + theme( + figure_size=(16, 9), + plot_title=element_text(size=24, weight="bold"), + axis_title=element_text(size=20), + axis_text=element_text(size=16), + legend_title=element_text(size=18), + legend_text=element_text(size=14), + legend_position="right", + panel_grid_major=element_line(color="#CCCCCC", size=0.3, alpha=0.5), + panel_grid_minor=element_blank(), + panel_background=element_rect(fill="#D4E8F7", alpha=0.5), # Ocean color + ) +) + +# Save at 300 DPI for 4800x2700 px output +plot.save("plot.png", dpi=300, verbose=False) From 80c3a1789892c98fe3fdd70db7ab324771cc3c73 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 10 Jan 2026 06:09:49 +0000 Subject: [PATCH 2/3] chore(plotnine): add metadata for bubble-map-geographic --- .../metadata/plotnine.yaml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 plots/bubble-map-geographic/metadata/plotnine.yaml diff --git a/plots/bubble-map-geographic/metadata/plotnine.yaml b/plots/bubble-map-geographic/metadata/plotnine.yaml new file mode 100644 index 0000000000..2d2ef25e6c --- /dev/null +++ b/plots/bubble-map-geographic/metadata/plotnine.yaml @@ -0,0 +1,19 @@ +# Per-library metadata for plotnine implementation of bubble-map-geographic +# Auto-generated by impl-generate.yml + +library: plotnine +specification_id: bubble-map-geographic +created: '2026-01-10T06:09:49Z' +updated: '2026-01-10T06:09:49Z' +generated_by: claude-opus-4-5-20251101 +workflow_run: 20873959857 +issue: 3625 +python_version: 3.13.11 +library_version: 0.15.2 +preview_url: https://storage.googleapis.com/pyplots-images/plots/bubble-map-geographic/plotnine/plot.png +preview_thumb: https://storage.googleapis.com/pyplots-images/plots/bubble-map-geographic/plotnine/plot_thumb.png +preview_html: null +quality_score: null +review: + strengths: [] + weaknesses: [] From 14991429f57e755ee5f6fe75c816992edfa626a3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 10 Jan 2026 06:12:32 +0000 Subject: [PATCH 3/3] chore(plotnine): update quality score 91 and review feedback for bubble-map-geographic --- .../implementations/plotnine.py | 6 +- .../metadata/plotnine.yaml | 204 +++++++++++++++++- 2 files changed, 200 insertions(+), 10 deletions(-) diff --git a/plots/bubble-map-geographic/implementations/plotnine.py b/plots/bubble-map-geographic/implementations/plotnine.py index b040b77d53..111cf588bc 100644 --- a/plots/bubble-map-geographic/implementations/plotnine.py +++ b/plots/bubble-map-geographic/implementations/plotnine.py @@ -1,7 +1,7 @@ -"""pyplots.ai +""" pyplots.ai bubble-map-geographic: Bubble Map with Sized Geographic Markers -Library: plotnine | Python 3.13 -Quality: pending | Created: 2026-01-10 +Library: plotnine 0.15.2 | Python 3.13.11 +Quality: 91/100 | Created: 2026-01-10 """ import numpy as np diff --git a/plots/bubble-map-geographic/metadata/plotnine.yaml b/plots/bubble-map-geographic/metadata/plotnine.yaml index 2d2ef25e6c..5120eb6f71 100644 --- a/plots/bubble-map-geographic/metadata/plotnine.yaml +++ b/plots/bubble-map-geographic/metadata/plotnine.yaml @@ -1,10 +1,7 @@ -# Per-library metadata for plotnine implementation of bubble-map-geographic -# Auto-generated by impl-generate.yml - library: plotnine specification_id: bubble-map-geographic created: '2026-01-10T06:09:49Z' -updated: '2026-01-10T06:09:49Z' +updated: '2026-01-10T06:12:32Z' generated_by: claude-opus-4-5-20251101 workflow_run: 20873959857 issue: 3625 @@ -13,7 +10,200 @@ library_version: 0.15.2 preview_url: https://storage.googleapis.com/pyplots-images/plots/bubble-map-geographic/plotnine/plot.png preview_thumb: https://storage.googleapis.com/pyplots-images/plots/bubble-map-geographic/plotnine/plot_thumb.png preview_html: null -quality_score: null +quality_score: 91 review: - strengths: [] - weaknesses: [] + strengths: + - Excellent use of scale_size_area() to properly scale bubble area (not radius) + to data values + - Clean, professional appearance with well-chosen colorblind-safe palette + - Comprehensive real-world dataset with 30 major cities across all continents + - Creative solution for basemap using simplified continent polygons via geom_polygon + - Good alpha transparency (0.7) for overlapping bubbles + - Proper coord_fixed(ratio=1.0) for accurate geographic projection + weaknesses: + - Grid lines are slightly too prominent (alpha=0.5, should be 0.2-0.4 for subtlety) + - Region legend shows tiny dots instead of circles that match the bubble aesthetic + image_description: 'The plot displays a world map visualization showing city populations + as sized bubbles. The background has a light blue color representing oceans, with + simplified gray continent polygons serving as a basemap (North America, South + America, Europe, Africa, Asia, and Australia). Bubbles are positioned at geographic + coordinates and sized proportionally to population (millions). Colors represent + regions: purple for Africa, blue for Asia, yellow for Europe, green for North + America, cyan for Oceania, and red for South America. The title "World City Populations + · bubble-map-geographic · plotnine · pyplots.ai" appears at the top in bold. Two + legends on the right show Population (M) with circles of sizes 10, 20, 30, and + Region with colored dots for each continent. Axis labels show Longitude (°) and + Latitude (°).' + criteria_checklist: + visual_quality: + score: 36 + max: 40 + items: + - id: VQ-01 + name: Text Legibility + score: 10 + max: 10 + passed: true + comment: Title at 24pt bold, axis labels at 20pt, tick labels at 16pt, legend + text at 14-18pt - all perfectly readable + - id: VQ-02 + name: No Overlap + score: 8 + max: 8 + passed: true + comment: No overlapping text elements, bubbles have appropriate transparency + - id: VQ-03 + name: Element Visibility + score: 6 + max: 8 + passed: true + comment: Bubble sizes well-adapted with alpha=0.7, though some smaller cities + could be slightly more visible + - id: VQ-04 + name: Color Accessibility + score: 5 + max: 5 + passed: true + comment: Uses colorblind-safe palette with distinct hues for each region + - id: VQ-05 + name: Layout Balance + score: 5 + max: 5 + passed: true + comment: Plot fills canvas well, legends positioned to the right, good use + of 16:9 aspect ratio + - id: VQ-06 + name: Axis Labels + score: 2 + max: 2 + passed: true + comment: 'Descriptive with units: Longitude (°) and Latitude (°)' + - id: VQ-07 + name: Grid & Legend + score: 0 + max: 2 + passed: false + comment: Grid is slightly too prominent (alpha=0.5), region legend markers + are very small dots + spec_compliance: + score: 23 + max: 25 + items: + - id: SC-01 + name: Plot Type + score: 8 + max: 8 + passed: true + comment: Correct bubble map with geographic context + - id: SC-02 + name: Data Mapping + score: 5 + max: 5 + passed: true + comment: Longitude/latitude correctly mapped, size encoding population + - id: SC-03 + name: Required Features + score: 4 + max: 5 + passed: true + comment: Has basemap, size legend, color grouping, transparency; missing minimum + bubble size + - id: SC-04 + name: Data Range + score: 3 + max: 3 + passed: true + comment: Full world coverage with xlim(-180, 180), ylim(-60, 80) + - id: SC-05 + name: Legend Accuracy + score: 2 + max: 2 + passed: true + comment: Both legends correctly labeled + - id: SC-06 + name: Title Format + score: 1 + max: 2 + passed: false + comment: Title is correct but spec-id should be more prominent + data_quality: + score: 20 + max: 20 + items: + - id: DQ-01 + name: Feature Coverage + score: 8 + max: 8 + passed: true + comment: Shows wide range of populations (3.4M to 37.4M), multiple regions, + geographic spread + - id: DQ-02 + name: Realistic Context + score: 7 + max: 7 + passed: true + comment: Uses real world cities with accurate population data + - id: DQ-03 + name: Appropriate Scale + score: 5 + max: 5 + passed: true + comment: Population values in millions are accurate for major world cities + code_quality: + score: 10 + max: 10 + items: + - id: CQ-01 + name: KISS Structure + score: 3 + max: 3 + passed: true + comment: 'Clean linear structure: imports → data → plot → save' + - id: CQ-02 + name: Reproducibility + score: 3 + max: 3 + passed: true + comment: Uses np.random.seed(42) + - id: CQ-03 + name: Clean Imports + score: 2 + max: 2 + passed: true + comment: All imports are used + - id: CQ-04 + name: No Deprecated API + score: 1 + max: 1 + passed: true + comment: Uses current plotnine API + - id: CQ-05 + name: Output Correct + score: 1 + max: 1 + passed: true + comment: Saves as plot.png + library_features: + score: 2 + max: 5 + items: + - id: LF-01 + name: Distinctive Features + score: 2 + max: 5 + passed: false + comment: Uses grammar of graphics with ggplot, scale_size_area, and theme + customization, but creates manual polygon basemaps rather than using dedicated + mapping features + verdict: APPROVED +impl_tags: + dependencies: [] + techniques: + - layer-composition + - custom-legend + patterns: + - data-generation + dataprep: [] + styling: + - alpha-blending + - grid-styling