|
| 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") |
0 commit comments