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()

Educoder Basemap和seaborn 第三关:Basemap_第1张图片

运用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)

Educoder Basemap和seaborn 第三关:Basemap_第2张图片

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

地图投影

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

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

投影简写-全称对照:

简写 全称
cyl Cylindrical Equidistant
merc Mercator
tmerc Transverse Mercator
omerc Oblique Mercator
mill Miller Cylindrical
gall Gall Stereographic Cylindrical
cea Cylindrical Equal Area
lcc Lambert Conformal
laea Lambert Azimuthal Equal Area
nplaea North-Polar Lambert Azimuthal
splaea South-Polar Lambert Azimuthal
eqdc Equidistant Conic
aeqd Azimuthal Equidistant
npaeqd North-Polar Azimuthal Equidistant
spaeqd South-Polar Azimuthal Equidistant
aea Albers Equal Area
stere Stereographic
npstere North-Polar Stereographic
spstere South-Polar Stereographic
cass Cassini-Soldner
poly Polyconic
ortho Orthographic
geos Geostationary
nsper Near-Sided Perspective
sinu Sinusoidal
moll Mollweide
hammer Hammer
robin Robinson
kav7 Kavrayskiy VII
eck4 Eckert IV
vandg van der Grinten
mbtfpq McBryde-Thomas Flat-Polar Quartic
gnom Gnomonic
rotpole Rotated 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)

Educoder Basemap和seaborn 第三关:Basemap_第3张图片

这里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()

Educoder Basemap和seaborn 第三关:Basemap_第4张图片

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

在地图上画数据

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');

Educoder Basemap和seaborn 第三关:Basemap_第5张图片

编程要求

本关的编程任务是补全右侧上部代码编辑区内的相应代码,中国地图已经绘制好,只需要读取输入参数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 *********#

你可能感兴趣的:(educoder,r语言,开发语言,python)