Skip to content

Commit 84db9dd

Browse files
feat(matplotlib): implement choropleth-basic (#3092)
## Implementation: `choropleth-basic` - matplotlib Implements the **matplotlib** version of `choropleth-basic`. **File:** `plots/choropleth-basic/implementations/matplotlib.py` **Parent Issue:** #3069 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/20620322402)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent d20a360 commit 84db9dd

2 files changed

Lines changed: 299 additions & 0 deletions

File tree

Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
1+
""" pyplots.ai
2+
choropleth-basic: Choropleth Map with Regional Coloring
3+
Library: matplotlib 3.10.8 | Python 3.13.11
4+
Quality: 91/100 | Created: 2025-12-31
5+
"""
6+
7+
import matplotlib.patches as mpatches
8+
import matplotlib.pyplot as plt
9+
from matplotlib.collections import PatchCollection
10+
11+
12+
# Data: US states arranged in a tile grid map layout (all 50 states)
13+
# Grid positions (col, row) - approximating geographic positions
14+
regions = {
15+
# Alaska and Hawaii (positioned separately)
16+
"Alaska": (0, 5),
17+
"Hawaii": (0, 1),
18+
# West Coast
19+
"Washington": (1, 5),
20+
"Oregon": (1, 4),
21+
"California": (0, 3),
22+
"Nevada": (1, 3),
23+
# Mountain West
24+
"Idaho": (2, 5),
25+
"Montana": (3, 5),
26+
"Wyoming": (3, 4),
27+
"Utah": (2, 3),
28+
"Arizona": (2, 2),
29+
"Colorado": (3, 3),
30+
"New Mexico": (3, 2),
31+
# Great Plains
32+
"North Dakota": (4, 5),
33+
"South Dakota": (4, 4),
34+
"Nebraska": (4, 3),
35+
"Kansas": (4, 2),
36+
"Oklahoma": (4, 1),
37+
"Texas": (3, 1),
38+
# Midwest
39+
"Minnesota": (5, 5),
40+
"Iowa": (5, 4),
41+
"Missouri": (5, 3),
42+
"Arkansas": (5, 2),
43+
"Louisiana": (5, 1),
44+
"Wisconsin": (6, 5),
45+
"Illinois": (6, 4),
46+
"Indiana": (7, 4),
47+
"Michigan": (7, 5),
48+
"Ohio": (8, 4),
49+
"Kentucky": (7, 3),
50+
"Tennessee": (6, 3),
51+
"Mississippi": (6, 2),
52+
"Alabama": (7, 2),
53+
# Southeast
54+
"Georgia": (8, 2),
55+
"Florida": (8, 1),
56+
"South Carolina": (9, 2),
57+
"North Carolina": (9, 3),
58+
"Virginia": (9, 4),
59+
"West Virginia": (8, 3),
60+
# Northeast
61+
"Pennsylvania": (10, 4),
62+
"New York": (10, 5),
63+
"Vermont": (11, 5),
64+
"New Hampshire": (11, 4),
65+
"Maine": (12, 5),
66+
"Massachusetts": (11, 3),
67+
"Rhode Island": (12, 3),
68+
"Connecticut": (11, 2),
69+
"New Jersey": (10, 3),
70+
"Delaware": (10, 2),
71+
"Maryland": (9, 1),
72+
# District of Columbia (no data - demonstrates missing data handling)
73+
"District of Columbia": (10, 1),
74+
}
75+
76+
# Population density values (simulated but realistic ranges)
77+
# Note: District of Columbia intentionally omitted to demonstrate missing data handling
78+
density_values = {
79+
"Alaska": 1,
80+
"Hawaii": 226,
81+
"California": 253,
82+
"Texas": 112,
83+
"Florida": 411,
84+
"New York": 408,
85+
"Pennsylvania": 286,
86+
"Illinois": 227,
87+
"Ohio": 289,
88+
"Georgia": 185,
89+
"North Carolina": 218,
90+
"Michigan": 177,
91+
"New Jersey": 1263,
92+
"Virginia": 218,
93+
"Washington": 117,
94+
"Arizona": 64,
95+
"Massachusetts": 901,
96+
"Tennessee": 167,
97+
"Indiana": 189,
98+
"Missouri": 89,
99+
"Maryland": 636,
100+
"Wisconsin": 108,
101+
"Colorado": 57,
102+
"Minnesota": 71,
103+
"South Carolina": 173,
104+
"Alabama": 99,
105+
"Louisiana": 107,
106+
"Kentucky": 114,
107+
"Oregon": 44,
108+
"Oklahoma": 58,
109+
"Connecticut": 733,
110+
"Iowa": 57,
111+
"Mississippi": 63,
112+
"Arkansas": 58,
113+
"Utah": 40,
114+
"Nevada": 28,
115+
"Kansas": 36,
116+
"New Mexico": 17,
117+
"Nebraska": 25,
118+
"West Virginia": 74,
119+
"Idaho": 23,
120+
"Maine": 44,
121+
"New Hampshire": 154,
122+
"Rhode Island": 1061,
123+
"Montana": 8,
124+
"Delaware": 508,
125+
"South Dakota": 12,
126+
"North Dakota": 11,
127+
"Vermont": 68,
128+
"Wyoming": 6,
129+
}
130+
131+
# Create figure
132+
fig, ax = plt.subplots(figsize=(16, 9))
133+
134+
# Create patches for each region
135+
patches = []
136+
missing_patches = []
137+
colors = []
138+
cmap = plt.cm.Blues
139+
140+
# Normalize values for coloring
141+
values = list(density_values.values())
142+
vmin, vmax = min(values), max(values)
143+
144+
for state, (col, row) in regions.items():
145+
# Create rectangle for each state (simplified grid representation)
146+
rect = mpatches.FancyBboxPatch(
147+
(col * 1.1, row * 1.1), 1.0, 1.0, boxstyle="round,pad=0.02,rounding_size=0.1", linewidth=2, edgecolor="white"
148+
)
149+
150+
# Handle missing data (state not in density_values)
151+
if state not in density_values:
152+
missing_patches.append(rect)
153+
else:
154+
patches.append(rect)
155+
# Get color based on density value
156+
density = density_values[state]
157+
norm_value = (density - vmin) / (vmax - vmin)
158+
colors.append(cmap(norm_value))
159+
160+
# Create patch collection for states with data
161+
collection = PatchCollection(patches, facecolors=colors, edgecolors="white", linewidths=2)
162+
ax.add_collection(collection)
163+
164+
# Create patch collection for missing data (gray with hatched pattern)
165+
missing_collection = PatchCollection(
166+
missing_patches, facecolors="#d0d0d0", edgecolors="white", linewidths=2, hatch="///"
167+
)
168+
ax.add_collection(missing_collection)
169+
170+
# Add state labels
171+
# State abbreviation dictionary (all 50 states + DC)
172+
abbrev = {
173+
"Alaska": "AK",
174+
"Hawaii": "HI",
175+
"Washington": "WA",
176+
"Oregon": "OR",
177+
"California": "CA",
178+
"Nevada": "NV",
179+
"Idaho": "ID",
180+
"Montana": "MT",
181+
"Wyoming": "WY",
182+
"Utah": "UT",
183+
"Arizona": "AZ",
184+
"Colorado": "CO",
185+
"New Mexico": "NM",
186+
"North Dakota": "ND",
187+
"South Dakota": "SD",
188+
"Nebraska": "NE",
189+
"Kansas": "KS",
190+
"Oklahoma": "OK",
191+
"Texas": "TX",
192+
"Minnesota": "MN",
193+
"Iowa": "IA",
194+
"Missouri": "MO",
195+
"Arkansas": "AR",
196+
"Louisiana": "LA",
197+
"Wisconsin": "WI",
198+
"Illinois": "IL",
199+
"Indiana": "IN",
200+
"Michigan": "MI",
201+
"Ohio": "OH",
202+
"Kentucky": "KY",
203+
"Tennessee": "TN",
204+
"Mississippi": "MS",
205+
"Alabama": "AL",
206+
"Georgia": "GA",
207+
"Florida": "FL",
208+
"South Carolina": "SC",
209+
"North Carolina": "NC",
210+
"Virginia": "VA",
211+
"West Virginia": "WV",
212+
"Pennsylvania": "PA",
213+
"New York": "NY",
214+
"Vermont": "VT",
215+
"New Hampshire": "NH",
216+
"Maine": "ME",
217+
"Massachusetts": "MA",
218+
"Rhode Island": "RI",
219+
"Connecticut": "CT",
220+
"New Jersey": "NJ",
221+
"Delaware": "DE",
222+
"Maryland": "MD",
223+
"District of Columbia": "DC",
224+
}
225+
226+
for state, (col, row) in regions.items():
227+
# Handle text color based on background
228+
if state not in density_values:
229+
# Missing data regions have gray background
230+
text_color = "#333333"
231+
else:
232+
density = density_values[state]
233+
norm_value = (density - vmin) / (vmax - vmin)
234+
text_color = "white" if norm_value > 0.5 else "#306998"
235+
236+
ax.text(
237+
col * 1.1 + 0.5,
238+
row * 1.1 + 0.5,
239+
abbrev.get(state, state[:2].upper()),
240+
ha="center",
241+
va="center",
242+
fontsize=13,
243+
fontweight="bold",
244+
color=text_color,
245+
)
246+
247+
# Set axis limits and remove axes
248+
ax.set_xlim(-0.5, 14)
249+
ax.set_ylim(0.3, 6.5)
250+
ax.set_aspect("equal")
251+
ax.axis("off")
252+
253+
# Add colorbar
254+
sm = plt.cm.ScalarMappable(cmap=cmap, norm=plt.Normalize(vmin=vmin, vmax=vmax))
255+
sm.set_array([])
256+
cbar = plt.colorbar(sm, ax=ax, shrink=0.6, aspect=20, pad=0.02)
257+
cbar.set_label("Population Density (per sq mile)", fontsize=18)
258+
cbar.ax.tick_params(labelsize=14)
259+
260+
# Add legend for missing data
261+
missing_patch = mpatches.Patch(facecolor="#d0d0d0", edgecolor="gray", hatch="///", label="No data")
262+
ax.legend(handles=[missing_patch], loc="lower left", fontsize=14, framealpha=0.9)
263+
264+
# Title
265+
ax.set_title(
266+
"US Population Density · choropleth-basic · matplotlib · pyplots.ai", fontsize=24, fontweight="bold", pad=20
267+
)
268+
269+
plt.tight_layout()
270+
plt.savefig("plot.png", dpi=300, bbox_inches="tight", facecolor="white")
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
library: matplotlib
2+
specification_id: choropleth-basic
3+
created: '2025-12-31T13:53:23Z'
4+
updated: '2025-12-31T14:16:44Z'
5+
generated_by: claude-opus-4-5-20251101
6+
workflow_run: 20620322402
7+
issue: 3069
8+
python_version: 3.13.11
9+
library_version: 3.10.8
10+
preview_url: https://storage.googleapis.com/pyplots-images/plots/choropleth-basic/matplotlib/plot.png
11+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/choropleth-basic/matplotlib/plot_thumb.png
12+
preview_html: null
13+
quality_score: 91
14+
review:
15+
strengths:
16+
- 'Successfully addressed all previous review feedback: Alaska/Hawaii now included,
17+
missing data handling demonstrated with DC'
18+
- Creative tile grid map approach eliminates need for external GIS dependencies
19+
(geopandas/shapely)
20+
- Excellent text contrast logic (white on dark tiles, blue on light tiles) ensures
21+
all labels are readable
22+
- Professional rounded tile design with white borders creates clean, modern appearance
23+
- Comprehensive coverage of all 50 US states with realistic population density values
24+
- Proper colorbar with units and legend for missing data pattern
25+
weaknesses:
26+
- State abbreviation font size (13pt) is functional but slightly small for optimal
27+
4800×2700 display; 14-15pt would improve readability
28+
- Layout slightly unbalanced with extra whitespace on left side due to Alaska/Hawaii
29+
placement

0 commit comments

Comments
 (0)