使用Folium绘制城市管道
Folium简介
Folium 是一个 Python 库,用于在地图上创建交互式可视化。它建立在 Leaflet.js 库的基础上,Leaflet.js 是一个开源的 JavaScript 库,用于创建交互式地图。Folium 为用户提供了一种简单的方式来将 Python 数据可视化为 Leaflet.js 地图,而不需要直接编写 JavaScript 代码。
Folium 的主要功能包括
-
简单易用: Folium 提供了简单易用的 API,使用户可以轻松地创建地图并添加标记、多边形、热力图等。
-
交互性:与 Pandas 和 NumPy 整合: Folium 可以轻松地与 Pandas 和 NumPy 库整合,使用户可以直接将数据集转换为地图可视化。
-
交互式可视化: Folium 创建的地图是交互式的,用户可以缩放、拖动地图,并与地图上的元素进行交互,例如点击标记以显示相关信息。
-
支持多种地图样式: Folium 支持多种地图样式,包括 OpenStreetMap、Stamen Terrain、Stamen Toner 等,用户可以根据自己的需求选择合适的地图样式。
-
扩展性: 用户可以通过自定义 JavaScript 和 CSS 代码来扩展 Folium 地图的功能和外观,从而满足更复杂的需求。
绘制城市管道
完整代码
先直接上代码,接下来进行代码逐一解释:
import webbrowser
import folium
import pandas as pd
# 从Excel文件中读取数据
df = pd.read_excel('location.xlsx', header=None)
# 提取坐标数据并处理NaN值
coords = {}
for i in range(len(df)):
row = df.iloc[i, :].astype(str).str.split(',', expand=True).astype(float)
row = row.dropna() # 删除NaN值
coords[f'pipeline_{i}'] = row.values.tolist()
city_map = folium.Map(location=[39.908823,116.39747], zoom_start=13, control_scale=True,
tiles="http://wprd04.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}",
attr='AutoNavi') # cartodbpositronnolabels "http://wprd04.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}"
# 创建FeatureGroup和PolyLine
for pipeline, coordinates in coords.items():
f = folium.FeatureGroup(f"管道 {pipeline.split('_')[-1]}")
line = folium.vector_layers.PolyLine(coordinates, popup=f'<b>管道 {pipeline.split("_")[-1]} </b>', color="black",
tooltip=f'<b>管道 {pipeline.split("_")[-1]} </b>', weight=3).add_to(f)
f.add_to(city_map)
folium.LayerControl().add_to(city_map)
city_map.save('gas_pipeline_map.html')
webbrowser.open_new_tab('gas_pipeline_map.html')
1. 导入包
import webbrowser
import folium
import pandas as pd
导入所需的Python库。webbrowser用于在浏览器中打开生成的地图,folium是用于创建地图的库,pandas用于处理数据。
2. 导入xlsx文件
df = pd.read_excel('location.xlsx', header=None)
这一行从名为location.xlsx(根据自己的文件名定义)的Excel文件中读取数据,并存储在一个Pandas的DataFrame对象df中。
xlsx数据结构如下:第一列管线编号,第二列及以后是每个管线的两端的经纬度坐标。
3. 数据处理
coords = {}
for i in range(len(df)):
row = df.iloc[i, :].astype(str).str.split(',', expand=True).astype(float)
row = row.dropna() # 删除NaN值
coords[f'pipeline_{i}'] = row.values.tolist()
这个循环迭代DataFrame中的每一行。它将每一行数据转换为列表,并将其存储在名为coords的字典中,键是pipeline_i,其中i是行号。
4.参数设置
city_map = folium.Map(location=[39.908823,116.39747], zoom_start=13, control_scale=True,
tiles="http://wprd04.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}",
attr='AutoNavi')
这一行创建了一个地图对象city_map,设定了地图的初始位置坐标(以北京市天安门广场为例)和缩放级别,并使用了高德地图作为底图。
更详细的参数设置请参考一下文章,在此不进行展开。
各种folium.Map样式介绍①
各种folium.Map样式介绍②
5.地图生成
for pipeline, coordinates in coords.items():
f = folium.FeatureGroup(f"管道 {pipeline.split('_')[-1]}")
line = folium.vector_layers.PolyLine(coordinates, popup=f'<b>管道 {pipeline.split("_")[-1]} </b>', color="black",
tooltip=f'<b>管道 {pipeline.split("_")[-1]} </b>', weight=3).add_to(f)
f.add_to(city_map)
这个循环遍历coords字典中的每个键值对,其中键是管道名称,值是该管道的坐标列表。然后,它为每个管道创建一个FeatureGroup,并在地图上绘制管道的路线。
folium.LayerControl().add_to(city_map)
这一行创建了一个图层控制器,允许用户在地图上选择显示哪些图层。
city_map.save('gas_pipeline_map.html')
webbrowser.open_new_tab('gas_pipeline_map.html')
这两行将地图保存为HTML文件,并在浏览器中打开这个HTML文件,以便查看生成的地图。
6.运行效果预览
因城市坐标管线为不公开数据,只展示局部信息并将底图信息隐藏。
代码改进
为了防止在绘制过程中,只有黑色的线条不利于区分不同的管段,现将代码进行改进,使得不同管线可以相互区分,代码如下:
import webbrowser
import folium
import pandas as pd
import numpy as np
# 从Excel文件中读取数据
df = pd.read_excel('location.xlsx', header=None)
# 提取坐标数据并处理NaN值
coords = {}
for i in range(len(df)):
row = df.iloc[i, :].astype(str).str.split(',', expand=True).astype(float)
row = row.dropna() # 删除NaN值
coords[f'vehicle_{i}'] = row.values.tolist()
city_map = folium.Map(location=[39.908823,116.39747], zoom_start=12, control_scale=True,
tiles="https://rt0.map.gtimg.com/tile?lang=zh_cn&size=1&style=7&z={z}&x={x}&y={-y}",
attr='AutoNavi') # "http://wprd04.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}"
# 创建FeatureGroup和PolyLine
for pipeline, coordinates in coords.items():
f = folium.FeatureGroup(f"管道 {pipeline.split('_')[-1]}")
# 生成随机颜色
color = "#{:06x}".format(np.random.randint(0, 0xFFFFFF))
line = folium.vector_layers.PolyLine(coordinates, popup=f'<b>管道 {pipeline.split("_")[-1]} </b>', color=color,
tooltip=f'<b>管道 {pipeline.split("_")[-1]} </b>', weight=5).add_to(f)
f.add_to(city_map)
folium.LayerControl().add_to(city_map)
city_map.save('gas_pipeline_map.html')
webbrowser.open_new_tab('gas_pipeline_map.html')
效果图如下: