首页城市定量分析【程序库】一键生成POI交...

【程序库】一键生成POI交互地图

计算机领域的发展趋势是开源共享,领域内的众多研究者、志愿者会将自己的代码、模型、数据放在诸如GitHub之类的互联网网站上,用户可以免费获得,并且可以基于一定规则自由地修改和分发。
本人在之前毕业论文写作过程中也是开源思想的受益者,使用到了很多开源的模型和数据集。
因此开启本系列内容,希望逐步打造成一个城市定量研究领域的开源代码仓库,让大家避免重复“造轮子”可以很方便地迁移到各自的研究或工作中。
因个人能力和时间均有限,本系列更新会较慢,因此希望有志同道合的朋友加入,共享自己的代码程序,加速代码仓库建设。
前往GitHub获取完整代码文件
https://github.com/returu/CityQuantHub
限于个人水平,不足之处在所难免,如若发现错误或有建议,欢迎留言交流。





01

项目概述



在之前的文章中分享了一些关于获取高德地图POI数据的代码以及GUI工具的相关内容:
【程序库】基于矩形区域的高德地图POI数据获取
【程序库】基于矩形区域的高德地图POI数据获取(GUI工具)

【程序库】基于行政区的高德地图POI数据获取

【程序库】基于行政区的高德地图POI数据获取(GUI工具)

本次主要介绍下如何将获取的CSV格式POI数据转换为交互式地图和SHP格式的地理数据文件。

需要注意的是,因为天地图无法使用该方式加载,因此默认使用的是OpenStreetMap地图作为底图,但是OSM数据存在着诸多政治错误(例如,钓鱼岛表示错误、错将台湾省按照国家表示、漏绘南海诸岛、国界线表示错误、错绘藏南地区国界线、错绘阿克赛钦地区国界线等),因此使用时需要格外注意,增强国家版图意识
02

代码解析



程序主要定义了一个名为create_poi_map的函数,它接受多个参数,这些参数分别用于指定输入文件路径、经纬度字段名、POI名称字段名、输出地图HTML路径、输出SHP文件路径、地图初始缩放级别、地图底图样式以及标记点颜色等,使得函数能够根据不同的需求进行个性化操作。

  • 1、导入库:

需要导入以下Python库:
import os
import pandas as pd
import geopandas as gpd
from shapely.geometry import Point
import folium
from folium.plugins import MarkerCluster
其中
  • pandas:用于读取和处理 CSV 格式的 POI 数据;

  • geopandas:基于 pandas 的地理空间数据处理库,是处理地理数据的核心工具;

  • shapely:用于几何对象操作的库,这里用于创建地理坐标点;

  • folium:基于 Leaflet.js 的 Python 地图库,用于创建交互式地图;

  • os:Python 标准库,用于文件和目录操作。

  • 2、函数定义:
create_poi_map函数的主要功能是从CSV文件中读取POI数据,并生成交互式地图和SHP文件。具体来说,该函数会执行以下步骤:
  • 数据读取与地理转换将普通表格数据转换为地理数据框架(GeoDataFrame),为每行数据创建Point几何对象,并指定WGS84坐标系(EPSG:4326)。
  • 地图创建与中心点计算为了创建交互式地图,代码使用了folium库。在创建地图之前,需要确定地图的中心点(通过调用unary_union.centroid方法,计算出所有POI点的几何中心,作为地图的中心点坐标),以便在初始显示时能够合理地覆盖POI数据。然后,根据这个中心点坐标、初始缩放级别以及指定的地图底图样式,创建了一个folium.Map对象。
  • 标记点添加与聚类优化:为了让每个POI在地图上以标记点的形式展示出来,并且能够显示其名称等信息,代码遍历GeoDataFrame中的每一行数据,使用folium.Marker为每个POI创建标记点。同时,为了优化大量标记点的显示效果,避免标记点过于密集而影响地图的可读性,代码引入了MarkerCluster模块,将所有标记点添加到聚类对象中,这样在地图缩放过程中,标记点会自动进行聚类和分散,提高了地图的交互性和用户体验。
  • 文件输出与保存:最后,可以选择性地将生成的交互式地图保存为HTML文件,以及将地理数据保存为SHP文件。需要注意的是,转换为Shapefile文件时,其字段名(列名)有严格限制,例如仅支持 ASCII 字符(不能直接使用中文、日文等非拉丁字符)且字段名长度 ≤ 10 个字符。

具体代码如下:

import os
import pandas as pd
import geopandas as gpd
from shapely.geometry import Point
import folium
from folium.plugins import MarkerCluster

def create_poi_map(
    file_path,
    longitude_field,
    latitude_field,
    poi_name_field,
    output_map_path,
    output_shp_path,
    zoom_start=10,
    tile_style='OpenStreetMap',
    marker_color='blue'
):
    """
    从CSV文件创建POI数据的交互式地图和SHP文件
    
    参数:
    - file_path: CSV文件路径
    - longitude_field: 经度字段名
    - latitude_field: 纬度字段名
    - poi_name_field: POI名称字段名
    - output_map_path: 输出地图HTML路径(None表示不保存)
    - output_shp_path: 输出SHP文件路径
    - zoom_start: 地图初始缩放级别
    - tile_style: 地图底图样式
    - marker_color: 标记点颜色
    
    返回:
    - folium.Map对象
    "
""
    # 读取CSV并创建GeoDataFrame
    poi_df = pd.read_csv(file_path)
    # 将DataFrame转换为GeoDataFrame,添加几何列(点坐标)
    # 每行数据根据经纬度创建Point对象,设置坐标系为WGS84
    poi_gdf = gpd.GeoDataFrame(
        poi_df,
        geometry = poi_df.apply(lambda row: Point(row[longitude_field], row[latitude_field]), axis=1),
        # geometry = gpd.points_from_xy(poi_df['lon'], poi_df['lat']), # 方法二
        crs="EPSG:4326"
    )
    
    # 计算地图中心点(所有POI的几何中心)
    # 使用unary_union.centroid获取所有点的几何中心
    map_center = [poi_gdf.unary_union.centroid.y, poi_gdf.unary_union.centroid.x]
    # 创建交互式地图
    # location: 地图中心点坐标
    # zoom_start: 初始缩放级别
    # tiles: 地图底图样式
    # control_scale: 显示比例尺
    # prefer_canvas: 使用Canvas渲染提高性能
    m = folium.Map(
        location=map_center,
        zoom_start=zoom_start,
        tiles=tile_style,
        control_scale=True,
        prefer_canvas=True
    )
    
    # 创建标记点聚类对象,用于优化大量标记点的显示
    marker_cluster = MarkerCluster().add_to(m)
    
    # 遍历POI数据,为每个点添加标记
    for idx, row in poi_gdf.iterrows():
        folium.Marker(
            location=[row[latitude_field], row[longitude_field]],
            popup=row[poi_name_field],
            icon=folium.Icon(color=marker_color, icon="info-sign"),
            tooltip=row[poi_name_field]
        ).add_to(marker_cluster)
    
    # 保存交互式地图为HTML文件
    if output_map_path:
        m.save(output_map_path)
    
    # 保存地理数据为SHP文件
    if output_shp_path:
         确保输出目录存在
        os.makedirs(os.path.dirname(output_shp_path), exist_ok=True)
        poi_gdf.to_file(output_shp_path, encoding='utf-8')
    
    return m

# 使用示例
if __name__ == "__main__":
    # 自定义参数使用
    map_obj = create_poi_map(
        file_path="POI.csv",
        longitude_field="WGS84_Lon",
        latitude_field="WGS84_Lat",
        poi_name_field="Name",
        output_map_path="custom_map.html",
        output_shp_path='./SHP/poi_data.shp',
        zoom_start=10,
        tile_style='OpenStreetMap',
        marker_color='blue'
    )
    
    # 在Jupyter Notebook中显示地图
    display(map_obj)
  • 3、输出结果:
在主程序部分通过自定义参数调用create_poi_map函数,生成交互式地图并保存为HTML文件和SHP文件。

在生成交互式地图时使用了MarkerCluster模块,在大比例尺下会将地图上靠近的POI标记点聚合成一个簇,并显示其数量。

当用户缩放地图时,簇会根据缩放级别自动展开或合并。


本篇文章来源于微信公众号: 码农设计师

RELATED ARTICLES

欢迎留下您的宝贵建议

Please enter your comment!
Please enter your name here

- Advertisment -

Most Popular

Recent Comments