6.3 描述性统计的可视化分析
初步研究数据的分布时,最直观的方法就是可视化分析了。本节将介绍一些基本的可视化分析方法,主要以seaborn和其自带的例子进行说明(使用自带的例子比使用金融收益率更容易展示其特点)。本节的主要目的是理解各种可视化图形的用途。这样在进行数据分析的时候,就能有的放矢的使用。
6.3.1 直方图
直方图(histogram)出现得很早,而且应用广泛。直方图是以一种图形方法来概括给定数值X的分布情况的图示。如果X是离散的变量,比如股票类型,则对于X的每个已知的值,画一个柱或竖直条。条的高度表示该X值出现的频率(即计数)。这种图更多地被称为条形图(bar chart)。
如果X是连续型变量,比如股票的市盈率,则会更多地使用术语直方图。在术语直方图里,X的值域被划分成不相交的连续子域。子域称为桶(bucket)或箱(bin),是X的数据分布的不相交子集。桶的范围称为宽度。通常,每个桶都是等宽的。比如,值为1~100的价格属性可以划分成子域1~20、21~40、41~60,等等。对于每个子域,画一个条,其高度表示在该子域观测到的商品的计数。
有时候,我们需要比较两个数据集的差异。比如,电子行业股票和房产行业股票的市盈率有什么差别。当然,此时可以用统计检验,但不够直观。
如何最直观地比较两个数据分布的差异呢?答案就是将两个数据分布画在一张图上。
下面举例说明一下,假设生成两个正态分布的数据集。
数据集1:均值为-1,标准差为2,1000个样本。
数据集2:均值为0,标准差为1,5000个样本。
示例代码如下:
import numpy as np import pandas as pd data_n1 = np.random.normal(-1,2,1000) data_n2 = np.random.normal(0,1,5000) data_n1=pd.DataFrame(data_n1,columns=['normal']) data_n2=pd.DataFrame(data_n2,columns=['normal'])
然后调用Pandas的plot.hist函数,绘制直方图,示例代码如下:
data_n1['normal'].plot.hist(bins=30,figsize=(10,6)) data_n2['normal'].plot.hist(bins=30,figsize=(10,6))
运行结果如图6-2所示。
图 6-2
这个图明显存在问题,蓝色的区域被红色大面积挡住了,看不太清楚(当然,如果是黑白显示,这里将会看不清楚,建议自行在电脑上画图尝试)。
对于这种情况,应该怎么办呢?可以加入一个参数alpha=0.5,增加图形的透明度。示例代码如下:
data_n1['normal'].plot.hist(bins=30,figsize=(10,6),alpha=0.5) data_n2['normal'].plot.hist(bins=30,figsize=(10,6),alpha=0.5)
运行结果如图6-3所示。
有了透明效果,两个分布就都能看到了。还有一个问题,数据集2有5000个样本,远多于数据集1的1000个。这里默认画的是绝对数量,所以数据集2看起来要格外高一些。
图 6-3
但我们需要的是相对概率,而不是绝对数量。因此可以再加入一个参数normed=True,来比较概率分布,示例代码如下:
data_n1['normal'].plot.hist(bins=30,figsize=(10,6),alpha=0.5,normed=True) data_n2['normal'].plot.hist(bins=30,figsize=(10,6),alpha=0.5,normed=True)
运行结果如图6-4所示。
图 6-4
这个图就直观多了。
6.3.2 散点图
散点图(scatter plot)是确定两个数值变量X、Y之间看上去是否存在联系,以及具有怎样的相关模式的最有效的图形方法之一。为构造散点图,将每个值对(x,y)视为一个代数坐标对,并作为一个点画在平面上。
散点图是一种观察双变量数据的有效方法。两个属性X和Y,如果一个属性和另一个属性有关系,则它们是相关的。相关可能是正的、负的或不相关。如果标绘点的模式是从左下向右上倾斜,则意味X的值随着Y值的增加而增加了,表示正相关。如果标绘点的模式从左上向右下倾斜,则意味着X的值随着Y值的减小而增加了,表示负相关。可以画一条最佳拟合线,研究变量之间的相关性。
本书的第4章已经介绍了如何使用matplotlib绘制散点图的方法。在实际应用中,使用seaborn来绘制散点图可能会更好。以下是一个示例:
import seaborn as sns sns.set(style="ticks") # Load the example dataset for Anscombe's quartet df = sns.load_dataset("anscombe") # Show the results of a linear regression within each dataset sns.lmplot(x="x", y="y", col="dataset", hue="dataset", data=df, col_wrap=2, ci=None, palette="muted", height=4, scatter_kws={"s": 50, "alpha": 1})
运行结果如图6-5所示。
详细解释一下,这里使用的是seaborn自带的一个数据集。这个数据集里面总共有四组数据,用罗马数字来代表组数。数据部分如下所示:
图 6-5
我们只需要按类似的格式将数据整理好,就可以使用seaborn.lmplot来画出各组的散点图,而且顺便也能将各组的线性回归直线也画出来。
从图6-5中可以看出,第1组和第3组的x,y值是正相关的。第2组的似乎是一个二次曲线。第4组除了一个异常点之外,其他所有点的x都是相同的。
这就是seaborn的好处,可以非常方便地用一个函数分析出不同数据组之间的相关性。
6.3.3 盒图
为了更加全面地了解一个分布,五数概括是一个很好的工具。五数概括由中位数、两个四分数、最小、最大值组成。按次序分别表示为Minimum,Q1,Median,Q3,Maximum。
盒图(boxplot)是一种流行的分布的图形表示。盒图就体现了五数概括的特点。
·盒的端点一般在四分位数上,使得盒的长度是四分位数极差IQR。
·中位数用盒内的线标记。
·盒外的两条线延伸到最小和最大的观测值。
seaborn也可以非常方便地画出盒图。以下是一个示例:
import seaborn as sns sns.set(style="ticks", palette="pastel") # Load the example tips dataset tips = sns.load_dataset("tips") # Draw a nested boxplot to show bills by day and time sns.boxplot(x="day", y="total_bill", hue="smoker", palette=["m", "g"], data=tips) sns.despine(offset=10, trim=True)
运行结果如图6-6所示。
图 6-6
同样地,这里也是使用了seaborn自带的数据集。这个数据集有好几个维度,比如sex(性别)、smoker(是否吸烟)、day(星期几)。统计数据有total_bill(总账单)、tip(小费)。
以上代码是将day作为x轴,用smoker作为第二维度,画出了total_bill的盒图(数据分布)。最中间的线就是中位数,实体上下边缘是四分位数,上下影线是最大最小值、灰点是异常值。
同理,我们也可以将第二维度选为sex,只需要将函数中的参数hue换为sex即可。代码如下:
sns.boxplot(x="day", y="total_bill", hue="sex", palette=["m", "g"], data=tips)
运行结果如图6-7所示。
图 6-7
可以看到,图6-7左上角的图例变为了sex。
值得注意的是,此例的数据结构与上例非常类似,这是一种常用的标准数据格式。只要我们将数据格式处理成这种数据格式,就可以非常方便地调用seaborn绘制出各种统计图形,进行数据的初步探索。
由此可见,在数据的描述统计上和可视化上,Python都提供了相当便捷的方法,可以迅速地进行数据探索和数据理清。