首页 > python教程

Python绘制地图神器folium的新人入门指南

时间:2021-06-09 python教程 查看: 2532

一、简介

想通过 Python 绘制精美的地图?想在地图上自由的设置各种参数?想获得灵活的交互体验?这里就有一款Python 神包满足你:folium。

folium 建立在 Python 生态系统的数据应用能力和 Leaflet.js 库的映射能力之上,在Python中操作数据,然后通过 folium 在 Leaflet 地图中可视化。

folium 相比较于国内百度的 pyecharts 灵活性更强,能够自定义绘制区域,并且展现形式更加多样化。

附:官方文档,官方示例,本文 notebook ,完整代码及数据。

二、安装方法

按照官方的教程即可,如果安装了 conda ,可以直接

conda install -c conda-forge folium

没有安装的话就使用

python3 -m pip install folium

三、主要功能

3.1 各级别地图

folium 显示地图的类为 folium.Map,类的声明如下

class folium.folium.Map(location=None, width='100%', height='100%', left='0%', top='0%', position='relative', tiles='OpenStreetMap', attr=None, min_zoom=0, max_zoom=18, zoom_start=10, min_lat=-90, max_lat=90, min_lon=-180, max_lon=180, max_bounds=False, crs='EPSG3857', control_scale=False, prefer_canvas=False, no_touch=False, disable_3d=False, png_enabled=False, zoom_control=True, **kwargs)

讲几个重要的参数

  • location 经纬度,list 或者 tuple 格式,顺序为 latitude, longitude
  • zoom_start 缩放值,默认为 10,值越大比例尺越小,地图放大级别越大
  • tiles 显示样式,默认*‘OpenStreetMap'*,也就是开启街道显示
  • crs 地理坐标参考系统,默认为"EPSG3857"

 3.1.1 世界地图

import folium

print(folium.__version__)

# define the world map
world_map = folium.Map()
# display world map
world_map

3.1.2 国家地图

# define the national map
national_map = folium.Map(location=[35.3, 100.6], zoom_start=4)
# display national map
national_map

3.1.3 市级地图

其实改变地图显示就是改变显示的经纬度和缩放比例,省级、市级、县级用法雷同,这里举一个市级的例子为例,如北京市:

# define the city map
city_map = folium.Map(location=[39.93, 116.40], zoom_start=10)
# display city map
city_map

显示效果确实是不如百度的😓。

3.2 地图形式

除了上述正常的地图显示外,folium 还提供了非常丰富的多样化显示,控制显示效果的变量是tiles,样式有OpenStreetMap, Stamen Terrain, Stamen Toner, Mapbox Bright, Mapbox Control Room等等,这里挑选几个比较常见的

# define the city map,tiles='Stamen Toner'
city_map = folium.Map(location=[39.93, 116.40], zoom_start=10, tiles='Stamen Toner')
# display city map
city_map
# define the city map, tiles='Stamen Terrain'
city_map = folium.Map(location=[39.93, 116.40], zoom_start=10, tiles='Stamen Terrain')
# display city map
city_map

3.3 在地图上标记

3.3.1 普通标记

添加普通标记用 Marker

这里可以选择标记的图案。

bj_map = folium.Map(location=[39.93, 115.40], zoom_start=12, tiles='Stamen Terrain')

folium.Marker(
    location=[39.95, 115.33],
    popup='Mt. Hood Meadows',
    icon=folium.Icon(icon='cloud')
).add_to(bj_map)

folium.Marker(
    location=[39.96, 115.32],
    popup='Timberline Lodge',
    icon=folium.Icon(color='green')
).add_to(bj_map)

folium.Marker(
    location=[39.93, 115.34],
    popup='Some Other Location',
    icon=folium.Icon(color='red', icon='info-sign')
).add_to(bj_map)

bj_map

添加圆形标记用 Circle 以及 CircleMarker

bj_map = folium.Map(location=[39.93, 116.40], zoom_start=12, tiles='Stamen Toner')

folium.Circle(
    radius=200,
    location=[39.92, 116.43],
    popup='The Waterfront',
    color='crimson',
    fill=False,
).add_to(bj_map)

folium.CircleMarker(
    location=[39.93, 116.38],
    radius=50,
    popup='Laurelhurst Park',
    color='#3186cc',
    fill=True,
    fill_color='#3186cc'
).add_to(bj_map)

bj_map

3.3.2 点击获取经纬度

m = folium.Map(location=[46.1991, -122.1889],tiles='Stamen Terrain',zoom_start=13)

m.add_child(folium.LatLngPopup())

m

通过点击鼠标便可以获取点击出的经纬度。

3.3.3 动态放置标记

m = folium.Map(
    location=[46.8527, -121.7649],
    tiles='Stamen Terrain',
    zoom_start=13
)

folium.Marker(
    [46.8354, -121.7325],
    popup='Camp Muir'
).add_to(m)

m.add_child(folium.ClickForMarker(popup='Waypoint'))

m

3.4 热力图绘制

因为没有实际的经纬度坐标数据,所以这里只能模拟一些位置出来,另外每个位置还需要一个数值作为热力值。

# generated data
import numpy as np
data = (
    np.random.normal(size=(100, 3)) *
    np.array([[0.1, 0.1, 0.1]]) +
    np.array([[40, 116.5, 1]])
).tolist()
data[:3]

数据分布

[[40.04666663299843, 116.59569796477264, 0.9667425547098781],
 [39.86836537517533, 116.28201445195315, 0.8708549157348728],
 [40.08123232852134, 116.56884585184197, 0.9104952244371285]]

绘制热力图

# HeatMap
from folium.plugins import HeatMap
m = folium.Map([39.93, 116.38], tiles='stamentoner', zoom_start=6)
HeatMap(data).add_to(m)
# m.save(os.path.join('results', 'Heatmap.html'))
m

3.5 密度地图绘制

folium 不仅可以绘制热力图,还可以绘制密度地图,按照经纬度进行举例聚类,然后在地图中显示。

from folium.plugins import MarkerCluster

m = folium.Map([39.93, 116.38], tiles='stamentoner', zoom_start=10)

# create a mark cluster object
marker_cluster = MarkerCluster().add_to(m)

# add data point to the mark cluster
for lat, lng, label in data:
    folium.Marker(
        location=[lat, lng],
        icon=None,
        popup=label,
    ).add_to(marker_cluster)

# add marker_cluster to map
m.add_child(marker_cluster)

3.6 自定义地图区域

folium 一个非常有优势的功能就是自定义区域的绘制了,只要有区域的边界数据,就可以在地图中以多种多样的形式展现出来,这里以 folium 官方的美国地图为例,源数据是一个 .json 文件,里面包含了各个地区(美国各州)的特征(包括边界经纬度列表、简称等),源数据传送门,其数据格式如下:

3.6.1 只绘制边界,不添加数据

如果只要求绘制边界,而不显示边界区域的相关信息,那么这个是比较容易的,代码如下

import json
import requests

# read us-states border 
with open("us-states.json") as f:
    us_states = json.load(f)

us_map = folium.Map(location=[35.3, -97.6], zoom_start=4)
folium.GeoJson(
    us_states,
    style_function=lambda feature: {
        'fillColor': '#ffff00',
        'color': 'black',
        'weight': 2,
        'dashArray': '5, 5'
    }
).add_to(us_map)

#display map
us_map

3.6.2 绘制边界,添加数据

当需要在各个区域填充数据的时候,这个稍微麻烦点,不仅需要各个区域的边界数据,还需要各个区域的显示信息,这里同样也使用官方的美国各州的边界数据为例:

import geopandas as gpd
import pandas as pd
import folium, branca

states = gpd.GeoDataFrame.from_features(us_states, crs=fiona.crs.from_epsg(4326))
states.head()

我们再把收入等数据连接到上表中

abbrs = pd.read_json(open("abbrs.json"))
statesmerge = states.merge(abbrs,how='left', left_on='name', right_on='name')
statesmerge['geometry']=statesmerge.geometry.simplify(.05)
income = pd.read_csv("income.csv", dtype={"fips":str})
income['income-2015']=pd.to_numeric(income['income-2015'], errors='coerce')
income.groupby(by="state")[['state','income-2015']].median().head()
statesmerge['medianincome']=statesmerge.merge(income.groupby(by="state")[['state','income-2015']].median(), how='left', left_on='alpha-2', right_on='state')['income-2015']
statesmerge['change']=statesmerge.merge(income.groupby(by="state")[['state','change']].median(), how='left', left_on='alpha-2', right_on='state')['change']
statesmerge.head()

最终绘制出的来的地图如下:

除此之外,还有很多非常有趣的功能,这里就不一一列举了,感兴趣的可以参考官方的文档。

四、竞品对比与优劣势

国内的竞品为百度的 pyecharts,和 folium 一样都可以实现普通的地图绘制功能,但是具体使用还有较大的区别,具体如下表

功能 pyecharts folium 备注
世界地图 可以 可以
中文显示 可以 部分可以 folium地图中标尺、文字不能正常显示,但是嵌入地图中的中文可以正常显示
交互性 好 好
区(县)级地图 可以 可以 folium需要区(县)边界数据
市级地图 可以 可以 folium需要市边界数据
收费 自定义区域需要购买百度ak 自定义区域功能免费
灵活性 好 好
省级地图 可以 可以 folium需要省边界数据
美观度 好 较好
自定义区域 部分可以 可以 pyecharts需要百度 ak,folium免费

五、参考资料

[1] https://www.zhihu.com/question/33783546

[2] https://pypi.org/project/folium/

[3] https://nbviewer.jupyter.org/github/python-visualization/folium/tree/master/examples/

到此这篇关于Python绘制地图神器folium的文章就介绍到这了,更多相关Python绘制地图folium内容请搜索python博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持python博客!

展开全文
上一篇:Python 解决空列表.append() 输出为None的问题
下一篇:教你利用python实现企业微信发送消息
输入字:
相关知识
Python 实现图片色彩转换案例

我们在看动漫、影视作品中,当人物在回忆过程中,体现出来的画面一般都是黑白或者褐色的。本文将提供将图片色彩转为黑白或者褐色风格的案例详解,感兴趣的小伙伴可以了解一下。

python初学定义函数

这篇文章主要为大家介绍了python的定义函数,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助,希望能够给你带来帮助

图文详解Python如何导入自己编写的py文件

有时候自己写了一个py文件,想要把它导入到另一个py文件里面,所以下面这篇文章主要给大家介绍了关于Python如何导入自己编写的py文件的相关资料,需要的朋友可以参考下

python二分法查找实例代码

二分算法是一种效率比较高的查找算法,其输入的是一个有序的元素列表,如果查找元素包含在列表中,二分查找返回其位置,否则返回NONE,下面这篇文章主要给大家介绍了关于python二分法查找的相关资料,需要的朋友可以参考下