添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
首发于 数学人生
如何用 PYTHON 绘制漂亮的地图?— FOLIUM 作图工具介绍

如何用 PYTHON 绘制漂亮的地图?— FOLIUM 作图工具介绍

Folium 简介

作为 Python 的一个可视化工具包 Folium,它通过 Leaflet 的地图服务,可以在 Jupyter Notebook 上实现可视化的地理位置作图,制作各种各样精美的地图信息。它不仅可以针对某个经纬度进行地理位置的可视化操作,还能够根据实时的人群地理位置信息来构建静态与动态热力图,甚至还能够针对经纬度的数量来进行必要的聚类可视化。本文将会基于新加坡的地图,对 Folium 的一些功能做简要的介绍,对此工具有兴趣的读者可以参阅 Folium 的官方文档。

创建地图

通过 Folium 工具,可以直接作出一张世界地图,其代码也十分地简洁明了。

import folium
%matplotlib inline  
import webbrowser
print(folium.__version__)
# define the world map
world_map = folium.Map()
# display world map
world_map
世界地图

除了能够作出一张完整的世界地图之外,通常程序员最常见的需求是针对某个或者某一些经纬度,来作出一张局部地图。地图中不仅需要包括经纬度信息,也需要有街道信息等必要的内容,甚至需要对经纬度的标记做一些必要的定制化工作。

在初始化一张地图的时候,需要指定它的经纬度信息,也就是 location 的位置。也需要根据需要放大的尺寸来指定相应的 zoom_start 值。另外,tiles 是 str 型,用于控制绘图调用的地图样式,默认为'OpenStreetMap',也有一些其他的内建地图样式,如'Stamen Terrain','Stamen Toner'。

有的时候需要在地图上标识出相应的经纬度,此时需要使用 folium.Marker 函数。其使用方法就是直接输入相应的经纬度信息,以及 icon 的形状(例如 'cloud', 'info-sign' 等);除此之外,还可以对其颜色进行标记,一般是对参数 color 进行调整即可。

另外,在某些经纬度上,还可以使用“点击-弹出“的控件 tooltip 和 popup,一旦鼠标指向该位置,就会呈现出相应的弹出信息。

# latitude and longitude in Singapore city
coordinate_sentosa = [1.248946, 103.834306]
coordinate_orchard_road = [1.304247, 103.833264]
coordinate_changi_airport = [1.357557, 103.98847]
coordinate_nus = [1.296202,103.776899]
coordinate_ntu = [1.34841, 103.682933]
coordinate_zoo = [1.403717, 103.793974]
coordinate_ang_mo_kio = [1.37008, 103.849523]
coordinate_yi_shun = [1.429384, 103.835028]
# icon 
icon_cloud = "cloud"
icon_sign = "info-sign"
# define the city map
# tiles in {'OpenStreetMap', 'Stamen  Terrain', 'Stamen Toner', 'Mapbox Bright'}
city_map = folium.Map(
    location=coordinate_orchard_road, 
    zoom_start=11, 
    tiles='OpenStreetMap')
# add marker in the city map
folium.Marker(
    coordinate_sentosa,
    icon=folium.Icon(color='blue')
).add_to(city_map)
folium.Marker(
    coordinate_orchard_road,
    icon=folium.Icon(color='green', icon=icon_cloud)
).add_to(city_map)
# add popup
folium.Marker(
    coordinate_changi_airport,
    popup='Changi Airport',
    icon=folium.Icon(color='red', icon=icon_sign)
).add_to(city_map)
# add tooltips and popup 
tooltip = "Click me!"
folium.Marker(
    coordinate_nus, 
    popup="<i>National University of Singapore</i>", 
    tooltip=tooltip
).add_to(city_map)
folium.Marker(
    coordinate_ntu, 
    popup="<b>Nanyang Technological University</b>", 
    tooltip=tooltip
).add_to(city_map)
# display city map
city_map
Folium 的经纬度作图(OpenStreetMap)
Folium 的经纬度作图(Stamen Terrain)
Folium 的经纬度作图(Stamen Toner)

有的时候,我们只知道某个地点,但是并不知道相应的经纬度数据,此时,只需要使用 folium.LatLngPopup() 就可以在鼠标指向位置上呈现相应的经纬度值,可以方便的查阅和使用。

# define the city map
city_map = folium.Map(location=coordinate_orchard_road, zoom_start=11)
# 在地图中添加经纬度, add latitude and longitude in the map when click
city_map.add_child(folium.LatLngPopup())
city_map

几何形状

在作出关键的经纬度点之后,有的时候我们需要作出相应的几何图形将其显示得更加清楚。Folium 提供线段相连,多边形,圆形,矩形等诸多图形,只需要使用相应的函数即可。

# define the city map
city_map = folium.Map(location=coordinate_orchard_road, zoom_start=11)
# 在地图中如何添加形状
# 多条边
points_1 = [
    coordinate_ntu,
    coordinate_nus,
    coordinate_zoo
# 在 city_map 中添加多条边,第一种添加方式
city_map.add_child(folium.PolyLine(
    locations=points_1, # 坐标列表
    weight=3, # 线条宽度
    color='gray'))
# 在 city_map 中添加多条边,第二种添加方式
folium.PolyLine(
    locations=points_1, # 坐标列表
    weight=3, # 线条宽度
    color='gray').add_to(city_map)
# 多边形
points_2 = [
    coordinate_orchard_road,
    coordinate_sentosa,
    coordinate_changi_airport
city_map.add_child(folium.Polygon(
    locations=points_2, # 坐标列表
    weight=3, # 线条宽度
    color='yellow'))
bounds = [
    coordinate_ang_mo_kio,
    coordinate_yi_shun
city_map.add_child(folium.Rectangle(
    bounds=bounds, # 坐标列表, Latitude and Longitude of line (Northing, Easting)
    weight=2, # 线条宽度
    color='blue'))
# 圆形, circle, radius units meters
folium.Circle(
    radius=1000,
    location=coordinate_nus,
    popup="National University of Singapore",
    color="crimson",
    fill=False,
).add_to(city_map)
# 圆形, circle, radius units pixels
folium.CircleMarker(
    location=coordinate_ntu,
    radius=30,
    popup="Nanyang Technological University",
    color="#3186cc",
    fill=True,
    fill_opacity=0.3, # 透明度
    fill_color="#3186cc",
).add_to(city_map)
city_map
Folium 中的画出各种形状

热力图

在实际使用经纬度信息的时候,通常来说会针对某个 APP 或者多款 APP 的实时经纬度信息来获取路况的拥挤程度,景区的人流量等信息,在这种情况下,就可以做出热力图。通过实时的热力图信息,我们可以获得相应的人流量信息进行必要的数据分析工作。

import numpy as np
from folium.plugins import HeatMap
# define the city map
city_map = folium.Map(location=coordinate_orchard_road, zoom_start=11)
# 构建随机数据
data = (
    np.random.normal(
        size=(10, 3)) * 0.03 * np.array([[1, 1, 1]]) +
        np.array([[coordinate_orchard_road[0], coordinate_orchard_road[1], 1]])
).tolist()
city_map.add_child(HeatMap(data=data))
city_map

除了单张图的热力图之外,Folium 还能够计算一段时间的连续热力图信息。

import numpy as np
from folium.plugins import HeatMapWithTime
# define the city map
city_map = folium.Map(location=coordinate_orchard_road, zoom_start=11)
# 使用 numpy 建立初始数据
initial_data = (np.random.normal(size=(200, 2)) *
                np.array([[0.02, 0.02]]) +
                np.array([coordinate_orchard_road]))
# 建立连续的数据
data = [initial_data.tolist()]
for i in range(20):
    data.append((data[i] + np.random.normal(size=(200, 2)) * 0.001).tolist())
# 显示连续的热力图
city_map.add_child(HeatMapWithTime(data)) 
city_map

经纬度点的聚类

除了热力图能反映人流量的信息,基于地理位置的聚类算法同样能够反映一个地区的拥挤程度,Folium 的 MarkerCluster() 函数可以对一个区域中的点来做聚类,在地图中可以放大和缩小,从而知道局部最拥挤的点在哪里了,最稀疏的区域是哪里。

from folium.plugins import MarkerCluster
# define the city map
city_map = folium.Map(location=coordinate_orchard_road, zoom_start=11)
# 经纬度的聚类
# 在 NUS 的经纬度附近随机生成 100 个点;
data = (
    np.random.normal(size=(100, 2)) 
    * np.array([[0.001, 0.001]]) +
    np.array([coordinate_nus]))
# create a mark cluster object
marker_cluster = MarkerCluster().add_to(city_map)
# 将这些经纬度数据加入聚类
for element in data:
    folium.Marker(location=[element[0], element[1]],icon=None).add_to(marker_cluster)