用 Python 和 GeoPandas 打造交互式中国地图选择器

在数据分析和可视化领域,地图是展示地理信息的强大工具。它能直观地揭示数据在空间上的分布模式。今天,我将带你深入了解一个使用 PythonwxPythonGeoPandas 构建的交互式中国地图行政区划选择器。这个应用不仅能让你轻松选择省份,还能将选定的区域高亮显示在地图上,并支持导出地图截图和自动保存状态。

C:\pythoncode\new\china_map_app.py

地图下载

DataV.GeoAtlas地理小工具系列

运行结果

技术栈概览

在深入代码之前,我们先了解一下这个项目使用的主要技术栈:

  • wxPython:一个用于创建图形用户界面(GUI)的跨平台 Python 库。它提供了丰富的控件和事件处理机制,是构建桌面应用的利器。

  • GeoPandas:一个强大的库,它扩展了 Pandas 的功能,使其能够处理地理空间数据。你可以把它看作是 Pandas 的地理空间版,可以方便地读取、操作和绘制 GeoJSON、Shapefile 等格式的地理数据。

  • Matplotlib:Python 中最流行的绘图库之一。GeoPandas 依赖它来完成地图的绘制。

  • Python 标准库:包括 json(用于读写应用状态)和 os(用于文件路径操作)。

整个应用的核心思想是:使用 wxPython 构建 GUI 框架,利用 GeoPandas 读取和渲染地图数据,再通过事件绑定将 GUI 按钮操作与地图的重新绘制联系起来。

代码结构分析

我们的应用主要由一个主窗口类 ChinaMapFrame 组成。让我们逐一剖析它的关键部分。

1. __init__ 方法:初始化与状态管理

__init__ 中,我们完成了应用的初始化工作:

Python

class ChinaMapFrame(wx.Frame):
    def __init__(self):
        super().__init__(None, title="中国地图行政区划选择器", size=(1200, 800))
        
        self.state_file = "map_state.json"
        
        # 定义所有省份列表
        self.provinces = [...] 
        # 定义省份名称映射,以兼容不同地图文件的命名方式
        self.province_mapping = {...}
        
        self.selected_provinces = set()
        self.gdf = None
        self.last_map_file = None # 存储上次加载成功的地图文件路径
        
        self.init_ui()
        self.load_state()
        self.load_geo_data()
        
        self.Bind(wx.EVT_CLOSE, self.on_close)

这里定义了几个重要的实例变量:

  • self.provinces:一个包含所有中国省份、自治区和直辖市的列表。

  • self.selected_provinces:一个 set 集合,用于高效地存储当前选中的省份,方便添加和删除。

  • self.gdf:GeoPandas 的核心数据结构,用于存储从 GeoJSON 或 Shapefile 文件加载的地理数据。

  • self.last_map_file:这是一个关键改进!它记录了上一次成功加载的地图文件路径,以便应用下次启动时能自动加载。

load_state()on_close() 方法负责应用的状态持久化。当程序关闭时,save_state() 会将 self.selected_provincesself.last_map_file 保存到 map_state.json 文件中。下次启动时,load_state() 会自动读取这个文件,恢复到上次关闭时的状态,这大大提升了用户体验。

2. init_ui 方法:构建用户界面

init_ui 方法负责构建整个窗口的布局和控件。它使用了 wx.BoxSizerwx.GridSizer 来组织界面。

Python

def init_ui(self):
    # ...
    # 上部分:地图区域,使用 FigureCanvas 承载 Matplotlib 图
    self.figure = Figure(figsize=(12, 8), dpi=80)
    self.canvas = FigureCanvas(panel, -1, self.figure)
    # ...
    # 下部分:按钮区域,使用 GridSizer 布局
    button_sizer = wx.GridSizer(rows=0, cols=6, hgap=5, vgap=5)
    # ...
    # 控制按钮,包括新增的“导出地图”按钮
    control_sizer.Add(load_btn, 0, wx.RIGHT, 10)
    control_sizer.Add(export_btn, 0)
    # ...

这里,FigureCanvasWxAgg 是连接 Matplotlib 图形和 wxPython 窗口的关键桥梁。地图将在 Matplotlib 的 Figure 对象上绘制,并通过 FigureCanvas 呈现在窗口中。

新增的“导出地图”按钮(export_btn)及其事件绑定,为用户提供了保存地图视图的功能。

3. load_geo_dataon_load_geo_file:数据加载逻辑

这两个方法是应用的核心数据加载部分。

  • load_geo_data 实现了智能加载。它首先检查 self.last_map_file 是否有效,如果有效则直接加载。如果无效,它会尝试加载几个预设的默认文件名(如 china.geojson)。这种设计保证了应用在大多数情况下都能找到并加载地图数据。

  • on_load_geo_file 则响应“加载地图文件”按钮的点击事件,通过文件对话框让用户手动选择地图文件。加载成功后,它会更新 self.last_map_file 并重新绘制地图。

4. create_map 方法:地图绘制核心

这是地图可视化的核心逻辑。它根据 self.selected_provinces 的状态,为每个行政区划分配不同的颜色,然后调用 GeoPandas 的 plot 方法进行绘制。

Python

def create_map(self):
    if self.gdf is None:
        self.show_no_data_message()
        return

    self.figure.clear()
    ax = self.figure.add_subplot(111)

    colors = []
    # 遍历 GeoDataFrame 的每一行
    for idx, row in self.gdf.iterrows():
        is_selected = False
        province_name = None
        # 尝试匹配不同的列名('name', 'NAME', 'province' 等)
        # ...
        
        # 匹配选中的省份
        if province_name:
            for selected_province in self.selected_provinces:
                # 使用直接匹配和映射匹配,提高兼容性
                # ...
                
        colors.append('#0066FF' if is_selected else '#E6F3FF')

    self.gdf.plot(ax=ax, color=colors, edgecolor='white', linewidth=0.5)
    # ... 绘制图例和标题 ...
    self.canvas.draw()

代码中的一个亮点是它对地图文件列名的鲁棒性。它会尝试匹配多个常见的列名('name', 'NAME', '省份' 等),以确保它能兼容不同来源的 GeoJSON 或 Shapefile 文件。

5. on_province_clickon_export_map:交互与导出

  • on_province_click 负责处理省份按钮的点击事件。它会 toggles(切换)省份在 self.selected_provinces 集合中的状态,并改变按钮的背景颜色,最后调用 create_map 来更新地图视图。

  • on_export_map 则是新增的导出功能。它使用 wx.FileDialog 弹出保存对话框,然后调用 self.figure.savefig(filepath, dpi=300) 将当前 Matplotlib 的 Figure 保存为高分辨率的 PNG 图片。

如何运行和使用?

要运行这个应用,请确保你已经安装了所有必需的库:

Bash

pip install wxpython geopandas matplotlib

然后,你需要一个中国行政区划的 GeoJSON 或 Shapefile 文件。你可以在 load_geo_data 方法中指定的几个默认文件名(china.geojson 等),或者在 GitHub 等网站找到类似的文件,然后通过“加载地图文件”按钮导入。

运行脚本后,你会看到一个包含中国地图和所有省份按钮的窗口。你可以:

  • 点击按钮来选择或取消选择省份。

  • 使用“全选”和“清除所有”按钮来快速操作。

  • 点击“导出地图”将当前视图保存为图片。

这个应用是一个很好的例子,展示了如何将多个 Python 库(GUI、地理空间数据、绘图)有机地结合起来,创建一个功能实用且用户友好的桌面工具。通过这种方式,你可以将复杂的数据处理和可视化任务封装在一个直观的界面中,大大降低了非技术人员的使用门槛。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值