使用Matplotlib & Cartopy绘制台风路径图

夏天一到,沿海地区经常会遭到台风的袭扰,可谓苦不堪言。

之前在公众号做过一个关于我国历史台风统计的可视化展示,发现很多有趣的数据,比如说台风登陆最多的城市是湛江。

image.png

大家可以去翻看历史文章,附有完整代码和数据,有兴趣做些可视化探索。

大数据告诉你,台风最喜欢在我国哪个省市登陆

这次的文章不研究台风数据,而是尝试用Python来绘制台风路径。


主要第三方库

用到的主要工具包有pandasnumpymatplotlibcartopyshapely,前三个库大家可能都熟悉,下面介绍下后两个库的使用场景。

cartopy:基于matplotlib的python地理数据处理和可视化库,本文会用来展示地图

shapely: 是一个对几何对象进行操作和分析的Python库,本文用来处理点线数据

台风路径数据

本文用到的数据是我国2017年所有台风路径,包含了时间、经纬度、强度等关键信息。

由于数据来源网络,没法追溯真实性,仅供练习。

原始数据比较乱,我重新处理了方便使用:


可以看到共有7个字段:

台风编号:我国热带气旋编号
日期:具体时间
强度:0~9
纬度:单位0.1度
经度:单位0.1度
中心气压:hPa
中心最大风速:m/s

绘制地图

台风路径需要在地图上展示,那么如何获取地图呢?

方式有很多种,既可以用离线的GeoJson数据,也可以用JPG图片,或者第三方库提供的地图。

我这里用的是cartopy内置的地图数据,可以很方便的修改配置属性。

首先导入本次会用到的所有库:

# cartopy:用来获取地图
import cartopy.crs as ccrs
import cartopy.feature as cfeature
# matplotlib:用来绘制图表
import matplotlib.pyplot as plt
# shapely:用来处理点线数据
import shapely.geometry as sgeom
import warnings
import re
import numpy as np
import pandas as pd
warnings.filterwarnings('ignore')
plt.rcParams['font.sans-serif'] = [u'SimHei']
plt.rcParams['axes.unicode_minus'] = False

获取我国沿海区域地图:

# 通过cartopy获取底图
fig = plt.figure(figsize=(10,10))
ax = fig.add_subplot(1, 1, 1, projection=ccrs.PlateCarree())

# 用经纬度对地图区域进行截取,这里只展示我国沿海区域
ax.set_extent([85,170,-20,60], crs=ccrs.PlateCarree())

# 设置名称
ax.set_title('2017年台风路径图',fontsize=16)

# 设置地图属性,比如加载河流、海洋
ax.add_feature(cfeature.LAND)
ax.add_feature(cfeature.OCEAN)
ax.add_feature(cfeature.COASTLINE)
ax.add_feature(cfeature.RIVERS)
ax.add_feature(cfeature.COASTLINE)
ax.add_feature(cfeature.LAKES, alpha=0.5)

# 展示地图
plt.show()

处理数据并可视化

先加载数据:

typhoonData = pd.read_csv('typhoonData.csv')

这个数据集包含了30个台风路径,所以后面要分别进行可视化。

再对数据进行处理,依次提取单个台风路径及其经纬度。

# 先对台风编号进行循环,提取单个台风数据
for typhoonNumber in typhoonData['台风编号'].unique():
    typhoon = typhoonData[typhoonData['台风编号']==typhoonNumber]
    # 再对单个台风数据进行处理,提取经纬度
    for typhoonPoint in np.arange(len(typhoon)-1):
        lat_1 = typhoon.iloc[typhoonPoint,3]/10
        lon_1 = typhoon.iloc[typhoonPoint,4]/10
        lat_2 = typhoon.iloc[typhoonPoint+1,3]/10
        lon_2 = typhoon.iloc[typhoonPoint+1,4]/10
        point_1 = lon_1,lat_1
        point_2 = lon_2,lat_2
        # 最后可视化
        ax.add_geometries([sgeom.LineString([point_1,point_2])],crs=ccrs.PlateCarree(),edgecolor='red')
        
    
# 展示图像
plt.show()

能看到所有台风路径都被描绘出来了。

但这里没有区别显示台风强度,一般是在.add_geometries()方法中添加参数调整。

有两种方式:

  • 用颜色区别:不同颜色代表不同强度,参数-edgecolor
  • 用线条粗细区别:越粗则强度越高,参数-linewidth
  1. 颜色区分
# 按强度区分颜色
def get_color(level):
    if level in (0,1):
        color='#ff00ff'
    elif level in (2,3):
        color='#ff00cc'
    elif level in (4,5):
        color='#ff0066'
    elif level in (6,7):
        color='#ff0033'
    elif level in (8,9):
        color='#ccff00'
    return color

# 先对台风编号进行循环,提取单个台风数据
for typhoonNumber in typhoonData['台风编号'].unique():
    typhoon = typhoonData[typhoonData['台风编号']==typhoonNumber]
    # 再对单个台风数据进行处理,提取经纬度
    for typhoonPoint in np.arange(len(typhoon)-1):
        lat_1 = typhoon.iloc[typhoonPoint,3]/10
        lon_1 = typhoon.iloc[typhoonPoint,4]/10
        lat_2 = typhoon.iloc[typhoonPoint+1,3]/10
        lon_2 = typhoon.iloc[typhoonPoint+1,4]/10
        point_1 = lon_1,lat_1
        point_2 = lon_2,lat_2
        # 最后可视化,添加颜色参数
        ax.add_geometries([sgeom.LineString([point_1,point_2])],crs=ccrs.PlateCarree(),edgecolor=get_color(typhoon.iloc[typhoonPoint,2]))
        
# 展示图像
plt.show()
  1. 线条粗细区分
# 先对台风编号进行循环,提取单个台风数据
for typhoonNumber in typhoonData['台风编号'].unique():
    typhoon = typhoonData[typhoonData['台风编号']==typhoonNumber]
    # 再对单个台风数据进行处理,提取经纬度
    for typhoonPoint in np.arange(len(typhoon)-1):
        lat_1 = typhoon.iloc[typhoonPoint,3]/10
        lon_1 = typhoon.iloc[typhoonPoint,4]/10
        lat_2 = typhoon.iloc[typhoonPoint+1,3]/10
        lon_2 = typhoon.iloc[typhoonPoint+1,4]/10
        point_1 = lon_1,lat_1
        point_2 = lon_2,lat_2
        # 最后可视化
        ax.add_geometries([sgeom.LineString([point_1,point_2])],crs=ccrs.PlateCarree(),linewidth = typhoon.iloc[typhoonPoint,2],edgecolor='red')
        
# 展示图像
plt.show()

最后

上文用比较简单的方式绘制了台风路径图,大家可以尝试换个三维地图,或者用动态显示台风走势...

玩法挺多的,赶紧尝试尝试吧。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,755评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,369评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,799评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,910评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,096评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,159评论 3 411
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,917评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,360评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,673评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,814评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,509评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,156评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,123评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,641评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,728评论 2 351

推荐阅读更多精彩内容