频次直方图、KDE和密度图


Seaborn的主要思想是用高级命令为统计数据探索和统计模型拟合创建各种图形,下面将介绍一些Seaborn中的数据集和图形类型。

虽然所有这些图形都可以用Matplotlib命令实现(其实Matplotlib就是Seaborn的底层),但是用 Seaborn API会更方便。

频次直方图、KDE和密度图

在进行统计数据可视化时,我们通常想要的就是频次直方图和多变量的联合分布图。在Matplotlib里面我们已经见过,相对比较简单:

 
 
  1. data = np.random.multivariate_normal([0, 0], [[5, 2], [2, 2]], size=2000)
  2. data = pd.DataFrame(data, columns=['x', 'y'])
  3. for col in 'xy':
  4. plt.hist(data[col], normed=True, alpha=0.5)

除了频次直方图,我们还可以用KDE获取变量分布的平滑估计。在seaborn通过sns.kdeplot来实现:

 
 
  1. for col in 'xy':
  2. sns.kdeplot(data[col], shade=True)

使用distplot可以将频次直方图和KDE结合起来:

 
 
  1. sns.distplot(data['x'])
  2. sns.distplot(data['y'])

如果向kdeplot输入的是二维数据集,那么就可以获得一个二维数据可视化图:sns.kdeplot(data)

矩阵图

当我们需要对多维数据进行可视化是,最终都要使用矩阵图,矩阵图对于探索多维数据不同维度间的相关性非常有效。

下面将用鸢尾花数据集来演示,其中有三种鸢尾花的花瓣与花萼数据:

 
 
  1. data = pd.read_csv("iris.csv")
  2. sns.pairplot(data,hue="species") #hue 选择分类列

分面频次直方图

有时观察数据最好的方法就是借助数据子集的频次直方图,SeabornFacetGrid函数让这件事变得非常简单。

来看看某个餐厅统计的服务员收取小费的数据:

 
 
  1. tips = pd.read_csv('tips.csv')
  2. g = sns.FacetGrid(tips, col="time", row="smoker")
  3. g = g.map(plt.hist, "total_bill", color="r")

条形图

对于时间序列数据可以使用sns.factorplot画出条形图,下面将使用行星数据来演示:

 
 
  1. planets = pd.read_csv('planets.csv')
  2. with sns.axes_style('white'):
  3. g = sns.factorplot("year", data=planets, aspect=2,
  4. kind="count", color='steelblue')
  5. g.set_xticklabels(step=5)

还可以对用不同方法发现行星的数量:

 
 
  1. with sns.axes_style('white'):
  2. g = sns.factorplot("year", data=planets, aspect=4.0, kind='count',
  3. hue='method', order=range(2001, 2015))
  4. g.set_ylabels('Number of Planets Discovered')

折线图

seaborn绘制折线图使用lineplot函数,该函数所传数据必须为一个pandas数组,这一点跟matplotlib里有较大的区别,并且一开始使用较为复杂。

首先sns.lineplot里有几个参数值得注意:

  • x:plot图的xlabel

  • y:plot图的ylabel

  • ci:与估计器聚合时绘制的置信区间的大小;

  • data: 所传入的pandas数组。

 
 
  1. x = np.linspace(100, 50, 6)
  2. y = np.array([0.194173876, 0.161086478, 0.138896531, 0.129826697, 0.133716787, 0.152458326])
  3. summary = []
  4. for i in range(6):
  5. x_t = x[i]
  6. y_t = y[i]
  7. summary.append([x_t, y_t])
  8. data =pd.DataFrame(summary )
  9. sns.lineplot(x=0,y=1,ci=None,data=data)

编程要求

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提供了几十种不同的投影的实现。

投影简写-全称对照:

简写 全称
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)

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

编程要求

猜你喜欢

转载自blog.csdn.net/qq_51250393/article/details/121323777