基于民意调查数据使用Python为埃及省份地图着色
Hey there! Since you already have matplotlib experience and know how to handle your CSV data, let's focus on the key part: turning your custom Photoshop map into a color-coded choropleth that shows voting intensity. Here's a step-by-step guide tailored to your setup:
1. Prepare Your Custom Map in Photoshop
First, when redrawing Egyptian provinces, optimize your file for Python integration:
- Assign a unique, solid RGB color to each province (e.g., pure red for Cairo, bright blue for Alexandria). Avoid similar shades—even tiny RGB differences will break the color-to-province mapping later.
- Save the map in one of two formats:
- PNG: For raster-based mapping, save with a transparent background and no color compression (to preserve exact RGB values).
- SVG: For vector precision (great for scaling), ensure each province is a separate path/group with a unique ID that matches the province names in your CSV. You may need to edit the SVG text file post-export to clean up IDs if Photoshop doesn't set them automatically.
2. Map CSV Data to Your Custom Map (Two Approaches)
We'll use matplotlib (your go-to tool) plus a few helper libraries to link your voting intensity data to the map.
Option A: Raster PNG Map (Best for Quick Setup)
This method uses your unique province colors to map data values directly to pixels:
import matplotlib.pyplot as plt import numpy as np import pandas as pd # Load your voting data (you know this part!) voting_df = pd.read_csv("egypt_voting_data.csv") voting_lookup = dict(zip(voting_df["province"], voting_df["intensity"])) # Load your custom PNG map map_img = plt.imread("egypt_provinces_custom.png") height, width, _ = map_img.shape # Create a color-to-province dictionary # Convert Photoshop's 0-255 RGB values to 0-1 floats (matplotlib's format) color_to_province = { (1.0, 0.0, 0.0): "Cairo", # Pure red in Photoshop = (255,0,0) (0.0, 1.0, 0.0): "Alexandria", # Pure green = (0,255,0) # Add all your province-color pairs here } # Set up colormap and normalization for intensity values cmap = plt.get_cmap("Reds") # Use Reds for intuitive "stronger" intensity norm = plt.Normalize(voting_df["intensity"].min(), voting_df["intensity"].max()) # Build the colored map colored_map = np.zeros_like(map_img) for y in range(height): for x in range(width): pixel_color = tuple(map_img[y, x][:3]) # Grab RGB values (ignore alpha if present) if pixel_color in color_to_province: province = color_to_province[pixel_color] intensity = voting_lookup[province] colored_map[y, x] = cmap(norm(intensity)) # Assign intensity color else: colored_map[y, x] = map_img[y, x] # Keep background/transparent pixels # Plot the final map plt.figure(figsize=(10, 8)) plt.imshow(colored_map) plt.axis("off") plt.title("Egypt Province Voting Intensity") # Add a colorbar for context sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm) sm.set_array([]) plt.colorbar(sm, label="Voting Intensity") plt.show()
Option B: Vector SVG Map (Best for High-Quality Scaling)
If you exported an SVG, use vector paths to fill provinces with intensity colors:
import matplotlib.pyplot as plt import pandas as pd from svgpathtools import svg2paths from descartes import PolygonPatch # Load voting data voting_df = pd.read_csv("egypt_voting_data.csv") voting_lookup = dict(zip(voting_df["province"], voting_df["intensity"])) # Load SVG paths and their attributes paths, attributes = svg2paths("egypt_provinces_custom.svg") # Set up colormap cmap = plt.get_cmap("Blues") norm = plt.Normalize(voting_df["intensity"].min(), voting_df["intensity"].max()) # Plot the map fig, ax = plt.subplots(figsize=(10, 8)) for path, attr in zip(paths, attributes): province_name = attr["id"] # Match SVG path IDs to CSV province names if province_name in voting_lookup: intensity = voting_lookup[province_name] # Convert SVG path to a polygon matplotlib can use polygon = path.polygonize() patch = PolygonPatch(polygon, color=cmap(norm(intensity)), edgecolor="black") ax.add_patch(patch) # Fit axes to the map bounds ax.set_xlim(paths[0].bbox()[0], paths[0].bbox()[2]) ax.set_ylim(paths[0].bbox()[1], paths[0].bbox()[3]) ax.axis("off") # Add colorbar sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm) sm.set_array([]) fig.colorbar(sm, ax=ax, label="Voting Intensity") plt.title("Egypt Province Voting Intensity") plt.show()
3. Quick Pro Tips
- Test Small First: Start with 2-3 provinces to verify the color mapping works before scaling to all of Egypt.
- Colormap Choices: Stick to perceptually uniform colormaps like
viridisorReds—avoidjetwhich can distort intensity perception. - SVG Cleanup: If your Photoshop-exported SVG has messy groups, use a free tool like Inkscape to simplify paths and assign clear IDs.
Content of the question originates from Stack Exchange, asked by Joe

