预计阅读

用 geopandas 绘制邵阳市各区县的人口分布图





我以前写过 10 篇用 R 语言绘制地图和空间数据可视化相关的博客。

  1. 【热门文章】R 语言画中国地图 找各种地图数据、检查数据可用性
  2. 【热门文章】空间数据可视化与 R 语言(上篇) 介绍空间数据操作 sf 包,用 echarts4r、 leaflet、plotly 和 lattice 包绘制可视化图形。
  3. 空间数据可视化与 R 语言(中篇) 找各类在线地图服务,结合在线地图绘制空间数据的各类可视化图形。
  4. 空间数据可视化与 R 语言(下篇) 不同类型的空间数据和不同的绘制方法。
  5. 【进阶】地区分布图及其应用 总结 R 语言中 7 种空间数据可视化的绘图方法。
  6. 【进阶】R 语言制作地区分布图及其动画 以动画的方式可视化空间数据(时空数据)。
  7. 【高阶】预测朗格拉普岛核辐射强度的分布 R 语言做空间分析和建模。
  8. 【进阶】中国常住人口分布图(2023 年市级) leaflet 包 可视化中国各市的常住人口数及其变化。
  9. 地震越来越频繁了吗? ggplot2 包绘制地图。
  10. highcharter 食谱 highcharter 包绘制地图。

今天,用一些 Python 模块绘制一幅邵阳市人口的空间分布图。

读取邵阳市的地图数据,这是一个 JSON 格式的数据。用 geopandas 模块读取该数据,之后,可以类似 pandas 模块那样操作数据。

import geopandas as gpd
shaoyang = gpd.read_file('data/邵阳市.json')
# 坐标参考系
shaoyang.crs
## <Geographic 2D CRS: EPSG:4326>
## Name: WGS 84
## Axis Info [ellipsoidal]:
## - Lat[north]: Geodetic latitude (degree)
## - Lon[east]: Geodetic longitude (degree)
## Area of Use:
## - name: World.
## - bounds: (-180.0, -90.0, 180.0, 90.0)
## Datum: World Geodetic System 1984 ensemble
## - Ellipsoid: WGS 84
## - Prime Meridian: Greenwich
# 查看前几行数据
shaoyang.head()
##    adcode  ...                                           geometry
## 0  430502  ...  MULTIPOLYGON (((111.60058 27.28676, 111.59138 ...
## 1  430503  ...  MULTIPOLYGON (((111.46854 27.24214, 111.46591 ...
## 2  430511  ...  MULTIPOLYGON (((111.48548 27.2898, 111.47899 2...
## 3  430522  ...  MULTIPOLYGON (((111.82375 27.44738, 111.81949 ...
## 4  430523  ...  MULTIPOLYGON (((111.66976 27.03255, 111.67033 ...
## 
## [5 rows x 10 columns]

显示了行数和列数,第一列和最后一列,中间列的数据都省略了。下面查看行政区域编码 ‘adcode’, 区县名称 ‘name’ 和地理边界 ‘geometry’ 三列。

shaoyang.loc[:, ['adcode', 'name', 'geometry']]
##     adcode     name                                           geometry
## 0   430502      双清区  MULTIPOLYGON (((111.60058 27.28676, 111.59138 ...
## 1   430503      大祥区  MULTIPOLYGON (((111.46854 27.24214, 111.46591 ...
## 2   430511      北塔区  MULTIPOLYGON (((111.48548 27.2898, 111.47899 2...
## 3   430522      新邵县  MULTIPOLYGON (((111.82375 27.44738, 111.81949 ...
## 4   430523      邵阳县  MULTIPOLYGON (((111.66976 27.03255, 111.67033 ...
## 5   430524      隆回县  MULTIPOLYGON (((110.64826 27.36729, 110.65633 ...
## 6   430525      洞口县  MULTIPOLYGON (((110.91961 27.02706, 110.92092 ...
## 7   430527      绥宁县  MULTIPOLYGON (((110.14853 26.9897, 110.14626 2...
## 8   430528      新宁县  MULTIPOLYGON (((110.58552 26.30133, 110.58702 ...
## 9   430529  城步苗族自治县  MULTIPOLYGON (((109.99175 26.26846, 109.99111 ...
## 10  430581      武冈市  MULTIPOLYGON (((110.54002 26.85363, 110.53864 ...
## 11  430582      邵东市  MULTIPOLYGON (((111.60058 27.28676, 111.60498 ...

邵阳市一共 12 个区县。还可以查看所有的列。

# 查看所有的列
shaoyang.columns
## Index(['adcode', 'name', 'center', 'centroid', 'childrenNum', 'level',
##        'parent', 'subFeatureIndex', 'acroutes', 'geometry'],
##       dtype='str')
# 查看所有的列的数据类型
shaoyang.dtypes
## adcode                int32
## name                    str
## center               object
## centroid             object
## childrenNum           int32
## level                   str
## parent               object
## subFeatureIndex       int32
## acroutes             object
## geometry           geometry
## dtype: object

绘制邵阳市区县级行政区划图,默认设置下的效果图。

shaoyang.plot()

有了地图数据集后,下面准备邵阳市各区县 2023年的常住年末户数(单位:万户)及人口(单位:万人)数据。

import pandas as pd
pop23 = pd.DataFrame(
    {
        "adcode": [430502, 430503, 430511, 430522, 430523, 430524, 430525, 430527, 430528, 430529, 430581, 430582],
        "name": ["双清区", "大祥区", "北塔区", "新邵县", "邵阳县", "隆回县", "洞口县", "绥宁县", "新宁县", "城步苗族自治县", "武冈市", "邵东市"],
        "household": [11.55, 14.14, 4.86, 19.94, 24.01, 35.18, 22.6, 10.83, 16.69, 7.67, 22.65, 36.59],
        "population": [32.01, 36.32, 12.37, 58.59, 71.45, 98.02, 65.71, 28.32, 49.78, 22.11, 62.01, 99.19]
    }
)
pop23
##     adcode     name  household  population
## 0   430502      双清区      11.55       32.01
## 1   430503      大祥区      14.14       36.32
## 2   430511      北塔区       4.86       12.37
## 3   430522      新邵县      19.94       58.59
## 4   430523      邵阳县      24.01       71.45
## 5   430524      隆回县      35.18       98.02
## 6   430525      洞口县      22.60       65.71
## 7   430527      绥宁县      10.83       28.32
## 8   430528      新宁县      16.69       49.78
## 9   430529  城步苗族自治县       7.67       22.11
## 10  430581      武冈市      22.65       62.01
## 11  430582      邵东市      36.59       99.19

调用 pandas 模块的 merge 方法将地图数据和常住人口数据合并至一个数据框内。

mydata = pd.merge(shaoyang.loc[:, ['name', 'geometry']], pop23, on="name")

最后,借助模块 geopandas 的 plot 方法 绘制可视化图形,指定要可视化的数据列,选择一个合适的调色板,显示图例。

mydata.plot(column="population", cmap='OrRd', legend=True)

matplotlib 模块内置的调色板还有很多,运行如下代码可查看。

from matplotlib import colormaps
# 多少个调色板
len(list(colormaps))
## 180
# 全部显示出来
df = pd.DataFrame(list(colormaps), columns=list("A"))
df["A"].to_numpy()
## array(['magma', 'inferno', 'plasma', 'viridis', 'cividis', 'twilight',
##        'twilight_shifted', 'turbo', 'berlin', 'managua', 'vanimo',
##        'Blues', 'BrBG', 'BuGn', 'BuPu', 'CMRmap', 'GnBu', 'Greens',
##        'Greys', 'OrRd', 'Oranges', 'PRGn', 'PiYG', 'PuBu', 'PuBuGn',
##        'PuOr', 'PuRd', 'Purples', 'RdBu', 'RdGy', 'RdPu', 'RdYlBu',
##        'RdYlGn', 'Reds', 'Spectral', 'Wistia', 'YlGn', 'YlGnBu', 'YlOrBr',
##        'YlOrRd', 'afmhot', 'autumn', 'binary', 'bone', 'brg', 'bwr',
##        'cool', 'coolwarm', 'copper', 'cubehelix', 'flag', 'gist_earth',
##        'gist_gray', 'gist_heat', 'gist_ncar', 'gist_rainbow',
##        'gist_stern', 'gist_yarg', 'gnuplot', 'gnuplot2', 'gray', 'hot',
##        'hsv', 'jet', 'nipy_spectral', 'ocean', 'pink', 'prism', 'rainbow',
##        'seismic', 'spring', 'summer', 'terrain', 'winter', 'Accent',
##        'Dark2', 'Paired', 'Pastel1', 'Pastel2', 'Set1', 'Set2', 'Set3',
##        'tab10', 'tab20', 'tab20b', 'tab20c', 'grey', 'gist_grey',
##        'gist_yerg', 'Grays', 'magma_r', 'inferno_r', 'plasma_r',
##        'viridis_r', 'cividis_r', 'twilight_r', 'twilight_shifted_r',
##        'turbo_r', 'berlin_r', 'managua_r', 'vanimo_r', 'Blues_r',
##        'BrBG_r', 'BuGn_r', 'BuPu_r', 'CMRmap_r', 'GnBu_r', 'Greens_r',
##        'Greys_r', 'OrRd_r', 'Oranges_r', 'PRGn_r', 'PiYG_r', 'PuBu_r',
##        'PuBuGn_r', 'PuOr_r', 'PuRd_r', 'Purples_r', 'RdBu_r', 'RdGy_r',
##        'RdPu_r', 'RdYlBu_r', 'RdYlGn_r', 'Reds_r', 'Spectral_r',
##        'Wistia_r', 'YlGn_r', 'YlGnBu_r', 'YlOrBr_r', 'YlOrRd_r',
##        'afmhot_r', 'autumn_r', 'binary_r', 'bone_r', 'brg_r', 'bwr_r',
##        'cool_r', 'coolwarm_r', 'copper_r', 'cubehelix_r', 'flag_r',
##        'gist_earth_r', 'gist_gray_r', 'gist_heat_r', 'gist_ncar_r',
##        'gist_rainbow_r', 'gist_stern_r', 'gist_yarg_r', 'gnuplot_r',
##        'gnuplot2_r', 'gray_r', 'hot_r', 'hsv_r', 'jet_r',
##        'nipy_spectral_r', 'ocean_r', 'pink_r', 'prism_r', 'rainbow_r',
##        'seismic_r', 'spring_r', 'summer_r', 'terrain_r', 'winter_r',
##        'Accent_r', 'Dark2_r', 'Paired_r', 'Pastel1_r', 'Pastel2_r',
##        'Set1_r', 'Set2_r', 'Set3_r', 'tab10_r', 'tab20_r', 'tab20b_r',
##        'tab20c_r', 'grey_r', 'gist_grey_r', 'gist_yerg_r', 'Grays_r'],
##       dtype=object)

实际上是 90 个调色板,后缀 _r 表示反向。

geopandas 还可以画各种常规图形,如散点图、折线图、箱线图、直方图。

mydata.plot(kind="scatter", x="household", y="population")

geopandas 还可以绘制交互图形,此时,需要安装额外的 Python 模块 folium (调用 leaflet.js)和 mapclassify 。

mydata.explore(column="population", tooltip="population", cmap='OrRd')
Make this Notebook Trusted to load map: File -> Trust Notebook

下面补充本文运行的环境。

reticulate::py_config()
## python:         /opt/.virtualenvs/r-tensorflow/bin/python
## libpython:      /opt/homebrew/opt/python@3.13/Frameworks/Python.framework/Versions/3.13/lib/python3.13/config-3.13-darwin/libpython3.13.dylib
## pythonhome:     /opt/.virtualenvs/r-tensorflow:/opt/.virtualenvs/r-tensorflow
## virtualenv:     /opt/.virtualenvs/r-tensorflow/bin/activate_this.py
## version:        3.13.11 (main, Dec  5 2025, 16:06:33) [Clang 17.0.0 (clang-1700.4.4.1)]
## numpy:          /opt/.virtualenvs/r-tensorflow/lib/python3.13/site-packages/numpy
## numpy_version:  2.3.4
## 
## NOTE: Python version was forced by RETICULATE_PYTHON_ENV

所用 Python 模块的版本,如下。

  • matplotlib 3.10.7
  • pandas 3.0.0
  • geopandas 1.1.3
  • shapely 2.1.2
  • folium 0.20.0
  • mapclassify 2.10.0

这是用到的几个 Python 模块的官方网站。

  1. https://github.com/geopandas/geopandas
  2. https://github.com/shapely/shapely
  3. https://matplotlib.org/stable/
  4. Scientific Visualization: Python + Matplotlib Nicolas P. Rougier, Bordeaux, November 2021. Matplotlib 高级绘图画廊。