Master Chinese Map Visualization with Python‑geopandas: A Step‑by‑Step Guide
This tutorial walks you through reading Chinese GeoJSON files, converting projections, preparing scatter data, and creating a detailed map with an inset of the South China Sea using Python‑geopandas, Matplotlib, and custom legends, while also covering installation tips and known limitations.
geopandas reads Chinese map files
geopandas provides a convenient read_file() method to load GeoJSON files. The example loads a provincial map and a nine‑dash line file, then plots them using the default WGS84 projection.
file = "中国省级地图GS(2019)1719号.geojson"
nine = "九段线GS(2019)1719号.geojson"
china_main = gpd.read_file(file)
china_nine = gpd.read_file(nine)
fig, ax = plt.subplots(figsize=(12, 8), dpi=80)
ax = china_main.plot(ax=ax)
ax = china_nine.plot(ax=ax)The resulting map is shown below:
Projection conversion and basic settings
Switch to EPSG:2343 and adjust visual properties:
fig, ax = plt.subplots(figsize=(12, 8), dpi=80)
ax = china_main.geometry.to_crs(epsg=2343).plot(fc="white", ec="black", ax=ax)
ax = china_nine.geometry.to_crs(epsg=2343).plot(ec="black", ax=ax)The key call is to_crs(epsg=2343) for projection transformation.
Data preparation
Scatter data is converted into a GeoDataFrame with geographic coordinates:
scattergdf = gpd.GeoDataFrame(
scatter,
geometry=gpd.points_from_xy(scatter.lon, scatter.lat),
crs="EPSG:4326"
)
scattergdf.head()After conversion, the data is re‑projected to EPSG:2343:
scattergdf_2343 = scattergdf.to_crs(epsg=2343, inplace=True)Map visualization
The main plotting code creates the base map, adds the South China Sea inset, and customizes legends:
fig, ax = plt.subplots(figsize=(8,5), dpi=200)
plt.rcParams['font.family'] = ['Times New Roman']
ax = china_main.geometry.to_crs(epsg=2343).plot(fc="white", ec="black", linewidth=.8, ax=ax)
ax = china_nine.geometry.to_crs(epsg=2343).plot(color="gray", linewidth=.9, ax=ax)
for loc, size, class_name in zip(
scattergdf_2343.geometry.representative_point(),
scattergdf_2343["data"],
scattergdf_2343["class"]):
ax.scatter(loc.x, loc.y, s=10*size, fc=class_color[class_name], ec="black", lw=.5, zorder=2)
# hide spines
for spine in ['top', 'left', 'bottom', 'right']:
ax.spines[spine].set_color("none")
ax.set_xlim(china_nine_2343.geometry[0].x-500000, china_nine_2343.geometry[1].x)
ax.set_ylim(china_nine_2343.geometry[0].y, china_nine_2343.geometry[1].y)
ax.set_xticks([])
ax.set_yticks([])
# custom legend points
ax.scatter([], [], c='#E21C21', s=30, label='cluster1', ec='black', lw=.5)
ax.scatter([], [], c='#3A7CB5', s=30, label='cluster2', ec='black', lw=.5)
ax.scatter([], [], c='#51AE4F', s=30, label='cluster3', ec='black', lw=.5)
# size legend
for i in range(1,6):
ax.scatter([], [], c='white', s=i*10, label=str(i), edgecolor='black', lw=.5)
ax.legend(frameon=False, ncol=8, loc='upper center', fontsize=9, columnspacing=.2)
ax.text(.91, -0.02, '
Visualization by DataCharm', transform=ax.transAxes, ha='center', va='center', fontsize=6, color='black')
# inset map for South China Sea
ax_child = fig.add_axes([0.688, 0.125, 0.2, 0.2])
ax_child = china_main.geometry.to_crs(epsg=2343).plot(ax=ax_child, fc='white', ec='black')
ax_child = china_nine.geometry.to_crs(epsg=2343).plot(ax=ax_child, color='gray', linewidth=.9)
for loc, size, class_name in zip(
scattergdf_2343.geometry.representative_point(),
scattergdf_2343["data"],
scattergdf_2343["class"]):
ax_child.scatter(loc.x, loc.y, s=10*size, fc=class_color[class_name], ec='black', lw=.5, zorder=2)
ax_child.set_xlim(china_nine_2343.geometry[2].x, china_nine_2343.geometry[3].x)
ax_child.set_ylim(china_nine_2343.geometry[2].y, china_nine_2343.geometry[3].y)
ax_child.set_xticks([])
ax_child.set_yticks([])Adding the inset map with add_axes() produces a focused view of the South China Sea.
The final visualization looks like this:
Summary
This issue demonstrates how to use Python‑geopandas for Chinese map drawing, covering data labeling, projection conversion, and custom legends. Note that geopandas installation can be tricky; using conda install -c conda-forge geopandas is recommended. Spatial visualizations still lack easy support for scale bars or north arrows, which are being improved.
Disclaimer: The data is for practice only and should not be used for research or publication.
Python Crawling & Data Mining
Life's short, I code in Python. This channel shares Python web crawling, data mining, analysis, processing, visualization, automated testing, DevOps, big data, AI, cloud computing, machine learning tools, resources, news, technical articles, tutorial videos and learning materials. Join us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
