Educoder Basemap和seaborn 第三关:Basemap

 第3关:Basemap(代码在下边)


任务描述

本关任务:以中国地图为背景绘制散点图。

相关知识

BasemapMatplotlib的一个子包,负责地图绘制。在数据可视化过程中,我们常需要将数据在地图上画出来。

比如说我们在地图上画出城市人口,飞机航线,军事基地,矿藏分布等等。这样的地理绘图有助于读者理解空间相关的信息。

  • 适用场景:适用于有空间位置的数据集。

安装和使用

相对于其他工具Basemap用起来有点笨重,就算做点儿简单的可视化图也需要花费比预期更长的时间。

在处理比较复杂的地图可视化任务时,更现代的解决方案可能会更适用一些,比如leafletGoogle Maps API。然而,Basemap 符合Python用户的使用习惯。

basemap并没有集成到matplotlib中,需要我们手动安装,basemap安装起来很简单,这里就不在说明。

安装并导入basemap工具箱后,只需要用几行代码就可以画出地理图:

 
  1. import matplotlib.pyplot as plt
  2. from mpl_toolkits.basemap import Basemap#导入工具包
  3. plt.figure(figsize=(8, 8))
  4. m = Basemap(projection='ortho', resolution=None, lat_0=50, lon_0=-100)
  5. m.bluemarble(scale=0.5)
  6. plt.show()

运用Basemap函数我们可以在绘图区域中绘制地理信息相关的图像,当参数 projection的值为'ortho'时,我们将得到一个如上图所示的地球仪截面。 将参数projection的值设置为lcc时,我们可以通过经纬度设置来得到某一区域的局部地图:

 
  1. fig = plt.figure(figsize=(8, 8))
  2. m = Basemap(projection='lcc', resolution=None,width=8E6,height=8E6,lat_0=45, lon_0=-100,)m.etopo(scale=0.5, alpha=0.5)
  3. # 将经纬度映射为 (x, y) 坐标,用于绘制图像
  4. x, y = m(-122.3, 47.6)
  5. plt.plot(x, y, 'ok', markersize=5)
  6. plt.text(x, y, ' Seattle', fontsize=12)

这里使用了两个额外参数,它们用来表示地图中心的纬度(lat_0)和经度( lon_0)。

地图投影

由于不可能把地表完美反映到二维平面上,所有的地图都是各种各样扭曲的产物,把这些扭曲的产物抹平到平面坐标系的过程,称为投影。

Basemap提供了几十种不同的投影的实现。

投影简写-全称对照:

简写全称
cylCylindrical Equidistant
mercMercator
tmercTransverse Mercator
omercOblique Mercator
millMiller Cylindrical
gallGall Stereographic Cylindrical
ceaCylindrical Equal Area
lccLambert Conformal
laeaLambert Azimuthal Equal Area
nplaeaNorth-Polar Lambert Azimuthal
splaeaSouth-Polar Lambert Azimuthal
eqdcEquidistant Conic
aeqdAzimuthal Equidistant
npaeqdNorth-Polar Azimuthal Equidistant
spaeqdSouth-Polar Azimuthal Equidistant
aeaAlbers Equal Area
stereStereographic
npstereNorth-Polar Stereographic
spstereSouth-Polar Stereographic
cassCassini-Soldner
polyPolyconic
orthoOrthographic
geosGeostationary
nsperNear-Sided Perspective
sinuSinusoidal
mollMollweide
hammerHammer
robinRobinson
kav7Kavrayskiy VII
eck4Eckert IV
vandgvan der Grinten
mbtfpqMcBryde-Thomas Flat-Polar Quartic
gnomGnomonic
rotpoleRotated Pole

下面我们对一常用的投影进行简单的演示。定义一个可以画带经纬线地图的简便方法:

 
  1. def draw_map(m, scale=0.2):
  2. # 画地貌晕渲图
  3. m.shadedrelief(scale=scale)
  4. # 用字典表示经纬度
  5. lats = m.drawparallels(np.linspace(-90, 90, 13))
  6. lons = m.drawmeridians(np.linspace(-180, 180, 13))
  7. # 字典的键是plt.Line2D示例
  8. lat_lines = chain(*(tup[1][0] for tup in lats.items()))
  9. lon_lines = chain(*(tup[1][0] for tup in lons.items()))
  10. all_lines = chain(lat_lines, lon_lines)
  11. # 用循环将所有线设置成需要的样式
  12. for line in all_lines:
  13. line.set(linestyle='-', alpha=0.3, color='w')

圆柱投影是最简单的地图投影类型,纬度线与经度线分别映射成水平线与竖直线。 采用这种投影类型的话,赤道区域的显示效果非常好,但是南北极附近的区域就会严重变形。

 
  1. fig = plt.figure(figsize=(8, 6), edgecolor='w')
  2. m = Basemap(projection='cyl', resolution=None,
  3. llcrnrlat=-90, urcrnrlat=90,
  4. llcrnrlon=-180, urcrnrlon=180, )
  5. draw_map(m)

这里basemap参数设置了左下角(llcrnr)和右上角(urcrnr)纬度(lat)和经度(lon)。不同的投影都有各种的优劣,大家之后可以多多尝试。

地图背景

basemap程序包中有许多实用的函数,可以画出各种地形的轮廓,如陆地、海洋、湖泊、河流、各国的政治分界线。

常用画图函数:

函数说明
drawcoastlines()绘制大陆海岸线
drawlsmask()为陆地与海洋设置填充色,从而可以在陆地或海洋投影其他图像
drawmapboundary()绘制地图边界,包括为海洋填充颜色
drawrivers()绘制河流
fillcontinents()用一种颜色填充大陆,用另一种颜色填充湖泊(可选)
drawcountries()绘制国界线
drawstates()绘制美国州界线
drawcounties()绘制美国县界线
drawgreatcircle()在两点之间绘制一个大圆
drawparallels()绘制纬线
drawmeridians()绘制经线
drawmapscale()在地图上绘制一个线性比例尺
bluemarble()绘制NASA 蓝色弹珠地球投影
shadedrelief()在地图上绘制地貌晕渲图
etopo()在地图上绘制地形晕渲图
warpimage()将用户提供的图像投影到地图上

如果要使用边界特征,就必须设置分辨率。通过resolution来设置分辨率,取值为c(原始分辨率)、l(低分辨率)、i(中分辨率)、h(高分辨率)、f(全画质分辨率)。

来看看两种不同分辨率的绘制效果:

 
  1. fig, ax = plt.subplots(1, 2, figsize=(12, 8))
  2. for i, res in enumerate(['l', 'h']):
  3. m = Basemap(projection='gnom', lat_0=57.3, lon_0=-6.2,
  4. width=90000, height=120000, resolution=res, ax=ax[i])
  5. m.fillcontinents(color="#FFDDCC", lake_color='#DDEEFF')
  6. m.drawmapboundary(fill_color="#DDEEFF")
  7. m.drawcoastlines()
  8. ax[i].set_title("resolution='{0}'".format(res));
  9. plt.show()

可以看出低分辨率不适合这个缩放,低分辨率适合呈现全局视角,而且加载速度比高分辨率更快。要呈现某一视角的适合,最好先从一个能快速呈现的分辨率开始,然后不断提高分辨率直到满意为止。

在地图上画数据

basemap还可以以地图为背景,在这上面画各种数据。basemap实例中许多方法都是与地图有关的函数。这些函数与标准matplotlib函数的用法类似,只是多了一个参数latlon。如果设置为true表示使用原来的经纬度坐标,不使用投影(x,y)坐标。

示例如下:

 
  1. import pandas as pd
  2. cities = pd.read_csv('california_cities.csv')
  3. # 提取我们感兴趣的数据
  4. lat = cities['latd'].values
  5. lon = cities['longd'].values
  6. population = cities['population_total'].values
  7. area = cities['area_total_km2'].values
  8. # 1. 绘制地图背景
  9. fig = plt.figure(figsize=(8, 8))
  10. m = Basemap(projection='lcc', resolution='h',
  11. lat_0=37.5, lon_0=-119,
  12. width=1E6, height=1.2E6)
  13. m.shadedrelief()
  14. m.drawcoastlines(color='gray')
  15. m.drawcountries(color='gray')
  16. m.drawstates(color='gray')
  17. # 2. 绘制城市数据的散点图,其中颜色反映人口
  18. # 尺寸反映面积
  19. m.scatter(lon, lat, latlon=True,
  20. c=np.log10(population), s=area,
  21. cmap='Reds', alpha=0.5)
  22. # 3. 创建颜色条和图例
  23. plt.colorbar(label=r'$\log_{10}({\rm population})$')
  24. plt.clim(3, 7)
  25. # 使用虚拟的点生成图例
  26. for a in [100, 300, 500]:
  27. plt.scatter([], [], c='k', alpha=0.5, s=a,
  28. label=str(a) + ' km$^2$')
  29. plt.legend(scatterpoints=1, frameon=False,
  30. labelspacing=1, loc='lower left');

编程要求

本关的编程任务是补全右侧上部代码编辑区内的相应代码,中国地图已经绘制好,只需要读取输入参数img_path作为绘图背景,x/y为散点图数据,需要设置散点图的参数为标记设置为o,大小为150,具体可视化要求如下:

  • 图形的figsize(10, 10)

  • 图形保存到Task3/img/T1.png

  • 具体要求请参见后续测试样例。

请先仔细阅读右侧上部代码编辑区内给出的代码框架,再开始你的编程工作!

测试说明

平台会对你编写的代码进行测试,对比你输出的数值与实际正确的数值,只有所有数据全部计算正确才能进入下一关。

测试输入:

无测试输入

预期输出: 生产图片与预期图片一致


开始你的任务吧,祝你成功!

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
from numpy import *
def student(img_path,x,y):
    # ********* Begin *********#
    fig=plt.figure(figsize=(10,10))
    imgP=plt.imread(img_path)
    plt.imshow(imgP)
    plt.scatter(x,y,marker='o',s=150)
    plt.savefig("Task3/img/T1.png")
    plt.show()
    # ********* End *********#

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值