https://github.com/returu/CityQuantHub
项目概述

代码解析
程序主要定义了一个名为create_poi_map的函数,它接受多个参数,这些参数分别用于指定输入文件路径、经纬度字段名、POI名称字段名、输出地图HTML路径、输出SHP文件路径、地图初始缩放级别、地图底图样式以及标记点颜色等,使得函数能够根据不同的需求进行个性化操作。
-
1、导入库:
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、函数定义:
-
数据读取与地理转换:将普通表格数据转换为地理数据框架(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、输出结果:
在生成交互式地图时使用了MarkerCluster模块,在大比例尺下会将地图上靠近的POI标记点聚合成一个簇,并显示其数量。

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



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