Python 的scientific stack(一个介绍Python科学计算包的网站)已经完全成熟,并且有各种各样用例的库,包括机器学习(链接:machine learning),数据分析(链接:data analysis)。数据可视化是探索数据和清晰的解释结果很重要的一部分,但是Python在过去却相对于其他工具比如R落后一点。
小编推荐大家可以加我的扣扣群 735934841 ,免费领取Python视频资料
幸运的是,近几年出现很多新的数据可视化Python库弥补了这个差距,matplotlib已经成为主要的数据可视化库,但是还有很多其它的库,比如vispy,bokeh,seaborn,pygal,folium,和networkx,他们都建立在matplotlib的基础之上,或者拥有matplotlib所不具有的功能。
在这篇文章中,我们将运用真实世界的数据,然后使用这些库进行数据的可视化。当我们这样做的时候,我们将发现,每个库最适合用在哪里,以及如何利用Python数据可视化系统最有效。
探索数据集
在我们进行数据可视化之前,让我们快速查看一下我们将要用到的数据集。我们将用到的据来自openflights。我们将用到 route,airport,和airline这三个数据。route数据的每一行对应两个机场之间的一条路线,以及相应的信息。arline数据的每一行对应一个航空公司。
首先,读入数据:
数据没有列标题,所以我们通过给columns这个属性赋值来添加列标题。我们想把每一列作为字符串来读入,这样做是为了后面基于id匹配行时,比较数据框方便一点。我们通过读取数据时设置dtype参数来达到目的。
我们可以快速看一下每个数据框:
airports.head()
部分数据截图:
airlines.head()
部分数据截图:
routes.head()
部分数据截图:
我们可以对每个数据集做各种各样有趣的探索,但是通过把这些数据集合并起来,我们能有最大的收获。当我们做数据分析的时候,Pandas可以帮助我们,因为它可以帮助我们很容易的过滤矩阵类型的数据,或着对矩阵数据使用某个函数。我们将深入一些有趣的度量,比如分析航空公司和航线。
在我们做这些之前,我们需要做一点数据清理的工作:
routes = routes[routes["airline_id"] != "N"]
这行代码保证我们airline_id的数据列中只包含数值型的数据。
绘制直方图
现在我们了解了数据结构,我们可以继续深入开始画图和探索数据。我们的第一个图,将使用matplotlib库。Matplotlib在Python中绘图库,是一个相对低水平的,所以为了画出一个看起来很漂亮的图,它通常要使用比其他的库需要更多的命令。另一方面,你几乎可以使用matplotlib绘制任何你想画的图。它非常灵活,但是灵活性带来的问题就是冗余问题。
我们首先绘制一个直方图来展示每个航空公司的航线长度的分布。直方图将所有的路线长度划分成范围(或着箱子),然后每个范围内的数据点进行计数。这可以告诉我们,航空公司飞长线多一点还是飞短线多一点。
为了达到这个目的,我们首先要计算航线的长度。第一步是一个距离公式,我们使用半正矢距离,也就是计算两个纬度,经度坐标对之间的距离。
然后我们可以定义一个功能,用来计算出发机场和目的机场之间的单程距离。想做这个,我们需要从routes这个数据框中提取出source_id和 dest_id两列,然后使用airports数据框的id列来进行匹配,从而得到这些机场的经度和纬度。然后接下来就是计算问题了,下面是这个功能函数:
如果source_id列 或着 dest_id列有无效的值,这个函数将会出错,所以我们要添加一个try/except模块来捕捉这些错误。
最后,我们使用pandas库来在routes数据框上使用这个计算距离的函数。这将得到一个pandas序列包含所有的航线长度。航线长度都是千米级的。
route_lengths = routes.apply(calc_dist, axis=1)
现在我们已经拥有了一系列的航线长度,我们可以创建一个直方图,将我们得到的值转换成范围,然后计算每个范围内有多少个数据点。
我们使用import matplotlib.pyplot as plt导入matplotlib的绘图功能。最后我们在使用%matplotlib inline命令将matplotlib的图表内嵌到ipython notebook中。最后我们可以使用plt.hist(route_lengths, bins=20)来绘制直方图啦。我们可以看到,航空公司的短航线要多于长航线。
使用Seaborn
我们可以使用python的高水平绘图库Seaborn,绘制出一样的图。Seaborn是基于matplotlib的,Seaborn用来绘制特定类型的图,它通常需要做一些比较简单统计工作。我们可以使用distplot函数来绘制一个顶端带有核密度估计的直方图。和密度估计是一条曲线,实质上是直方图的平滑以后的版本,这样能使我们更容易发现里面的模式。
import seaborn
seaborn.distplot(route_lengths, bins=20)
如图所示,Seaborn相比于matplotlib拥有更好的默认风格。对于matplotlib的所有绘图,Seaborn里面并没有自己对应的版本,但是,使用Seaborn来快速绘制一个好看的,并且比matplotlib默认的图表更加深入的图表,是一个不错的方式。如果你想要继续深入,或着做更多的统计工作,Seaborn是一个很好的库。
条形图
直方图很好,但是或许我们想看一下航空公司的平均航线长度。这时我们就可以使用条形图,每条航线会单独对应条形图里面的一条,告诉我们每个航空公司的平均航线长度。这可以告诉我们哪些航班是飞本地区的,哪些是国际的。我们可以使用pandas,python的一个数据分析库,计算出每个航空公司的平均航线长度。
首先,构造一个航空公司id和航线长度的数据框,我们把route_length_df基于airline_id来分组。实际上就是,每个航空公司构造一个数据框。然后使用pandas的aggregate函数对每个数据框里面的length这一列求平均,然后再把计算结果重新组合成一个新的数据框。然后对数据框进行排序,把路线最多的航空公司放在最前面。
然后我们可以把它用matplotlib画出来
plt.bar(range(airline_route_lengths.shape[0]),
airline_route_lengths["length"])
Matplotlib的plt.bar方法可以画出每个airline文件中(airline_route_lengths["length"])的航线—平均长度的关系图。flies(airline_route_lengths["length"])
上述图的问题是我们不能很容易的看出哪家航空公司拥有什么航线长度。所以我们需要看到坐标轴标签。这有一点难,因为有太多的航空公司了。一种能使这个工作变得简单的方法就是绘制交互图,它允许我们放大或缩小来查看标签。我们可以使用bokeh库——它使绘制交互图和意义伸缩的图会变得简单。
为了使用bokeh,我们首先需要预处理一下我们的数据:
上面的代码可以获取airline_route_lengths中每一行数据的名字,并添加在name这一列中,name这一列包含了每一个航空公司的名字,我们还添加了id这一列,用来做查找(apply函数不传递索引值)。
最后我们重置索引来得到所有的唯一值,没有这一步bokeh就不能正常的工作。
现在,我们继续我们的图表问题:
我们使用output_notebook创建背景虚化,在iPython的 notebook 里画出图。然后我们使用数据框和指定的列绘制条形图,最后,使用show函数显示出画好的图。
在notebook中产生的图并不是图像,它实质上是一个java插件,也正因为如此,我们在下面展示的是一个屏幕截图,而不是真正的图表。
有了这个图,我们可以放大,看哪一趟航班的航线最长。上图的标签看起来都堆叠在了一起,但是当你放大以后就很容易看清楚了。
水平条形图
Pygal是python的一个数据分析库,它能够快速的绘制出很有吸引力的图。我们可以用它来对路线按长度进行拆分。首先,我们把我们的路线分成短,中,长三类,并计算出在route_lengths中每一类所占的百分比。