关系数据可视化 关系数据是指变量之间存在着一定的相关关系。关系数据可视化的目的是通过图形 的方式探索变量之间的隐含关系。本章将介绍关系数据可视化的典型表现形式:散点 图、气泡图和直方图等,并通过Python语言实现。 5.1 散 点 图 散点图也称X-Y图,它将所有的数据以点的形式展现在直角坐标系上,以显示变量 之间的相互影响程度,点的位置由变量的数值决定(如图5-1所示)。通过观察散点图上 数据点的分布情况可以推断出变量间的相关性。如果变量之间不存在相互关系,那么在 散点图上就会表现为随机分布的离散的点;如果存在某种相关性,那么大部分的数据点就 会相对密集并以某种趋势呈现。那些离点集群较远的点称为离群点或者异常点。 图5-1 散点图 5.1.1 单一散点图 散点图通常用于比较跨类别的聚合数据,表示因变量随自变量而变化的大致趋势,通 过两组数据构成多个坐标点,考察坐标点的分布,判断两变量之间是否存在某种关联关 系。散点图通常用于显示和比较数值,例如科学数据、统计数据和工程数据。 5 80 可以利用方法matplotlib.pyplot.hist.scatter(x,y,s,c,marker)绘制散点图,下面 解释一下常用的参数。 ① x:指定散点图的x 轴数据。 ② y:指定散点图的y 轴数据。 ③s:指定散点图点的大小,默认为20。 ④c:指定散点图点的颜色,默认为蓝色。 ⑤ marker:指定散点图点的形状,默认为圆形。 本节利用消费与小费关系数据集tips(如图5-2所示)绘制散点图。tips是Seaborn自带 数据集,可以使用importseabornassnstips=snsl.oad_dataset(t'ips')导入数据集,然而自带 数据集的导入通常受到网络环境的限制,此时可利用离线数据集tips.txt作为数据源。 第一步首先查看数据集基本状况。 import pandas as pd tips = pd.read_csv('tips.txt', index_col=False) print(tips.head()) 图5-2 tips数据集 tips数据集包含7个属性:总消费,小费,性别,吸烟与否,就餐星期,就餐时间,就餐人数。 还可以通过tips.shape查看数据集大小,为(244,7)。下面针对tips数据集绘制散点图。 Matplotlib绘制散点图有两种方法。一种是利用折线图的matplotlib.pyplot.plot(), 此时需要将线条指定为‘o’,这里采用‘ro’设置标记点为红色圆点。图5-3(a)中子图为未 设置图标形状,默认将被绘制为折线图,图5-3(b)采用plt.plot(tips['total_bill'], tips[t'ip'],r' o')设置标记点形状即可呈现为散点图。 图5-3 利用plt.plot()绘制散点图 81 还可以直接采用matplotlib.pyplot.scatter()直接绘制散点图:plt.scatter(tips[t' otal _bill'],tips[t'ip'],color= g' ')(如图5-4所示)。 图5-4 利用plt.scatter()绘制散点图 完整代码如下。 import matplotlib.pyplot as plt import pandas as pd plt.rcParams['font.sans-serif'] = ['SimHei'] tips = pd.read_csv('tips.txt', index_col=False) plt.scatter(tips['total_bill'],tips['tip'],color = 'g') plt.title('tips 散点图') plt.xlabel('total bill') plt.ylabel('tips') plt.show() 通过tips散点图反映出小费金额集中区间为10~20,同时随着用餐费用的上升,小 费又有随之上升的趋势。反映大规模数据的聚集程度是散点图的优势之一。如果数据集 规模过小,则难以显示散点图的优势;而当数据集规模庞大,则应通过参数alpha设置点 的透明度,避免由于大规模数据叠加而产生面积粘连,设置合适的透明度,将使得数据聚 集程度通过色彩的饱和度很好地表现出来。 5.1.2 分类散点图 散点图中包含的数据越多,比较的效果就越好。对于处理值的分布和数据点的分簇, 散点图均表现得十分理想。如果数据集中包含非常多的点,那么散点图便是最佳图表类 型。默认情况下,散点图以圆圈显示数据点。当散点图中存在多个序列,可以考虑改变每 个点的形状或者颜色。 以上述tips数据集为例,期望观察不同性别对小费金额的影响,可以对散点图进行 82 性别分类绘制。对于数据集的分类,既可以通过pandas.DataFrame.groupby()方法,也可 以使用seaborn的散点图对属性进行自动分类。首先来实现第一种方法分类绘制散点 图。DataFrame.groupby()方法能够根据指定属性对数据集自动分组,并返回重构格式 的DataFrame。数据重构后,指定属性的值将会变为索引,此时可以通过get_group('key') 对指定键值的分组进行提取。首先通过属性sex对数据集分组,然后对分组对象分别提 取.get_group('Female')和.get_group('Male'),得到女士、男士两组小费数据集,即可使用 plt.scatter()方法设定不同的颜色呈现两组数据的小费数值表现(如图5-5所示)。 tips_temp=tips.groupby('sex') female_set=tips_temp.get_group('Female') male_set=tips_temp.get_group('Male') plt.scatter(female_set['total_bill'],female_set['tip'],color = 'b') plt.scatter(male_set['total_bill'],male_set['tip'],color = 'r') 图5-5 groupby分组分类散点图 当使用seaborn进行分类散点图绘制时,一切会变得非常简单,只需要为分类参数 hue赋值为期望分类的属性即可:seaborn.scatterplot(x="total_bill",y="tip",hue= "sex",data=tips)。通过分类散点图可以清晰地看出,在小费金额方面,男性顾客对于小 费更加慷慨,而女性顾客则更大概率地留下更少的小费(如图5-6所示)。 完整代码如下。 import matplotlib.pyplot as plt import pandas as pd import seaborn as sns plt.rcParams['font.sans-serif'] = ['SimHei'] tips = pd.read_csv('tips.txt', index_col=False) sns.scatterplot(x="total_bill", y="tip", hue="sex",data=tips) plt.xlabel('total bill') 83 plt.ylabel('tips') plt.show() 图5-6 seaborn分类散点图 5.2 气 泡 图 气泡图(bubblechart)可用于展示3个变量之间的关系,它与散点图类似,绘制时将 一个变量放在横轴,另一个变量放在纵轴,而第三个变量则用气泡的大小来表示。气泡图 与散点图的不同之处在于:气泡图允许在图表中额外加入一个表示大小的变量进行 对比。数 据集crimeRatesByState2005.csv为美国各州各种犯罪行为的发生率(每10万人 口),如图5-7所示。我们期望发现各州谋杀率和入室盗窃率之间是否有关联,同时把各 州的人口显示出来,以此判断人口多的州这两种犯罪率是否也会更高。 数据集下载地址为http://datasets.flowingdata.com/crimeRatesByState2005.csv。 第一步导入并观察数据集,利用切片将第一行的平均数据去除。crime=pd.read_csv (r"http://datasets.flowingdata.com/crimeRatesByState2005.csv")crime=crime[1:]。 图5-7 crimeRatesByState2005.csv 在绘制散点图时,以murder(谋杀率)为x 轴,burglary(盗窃率)为y 轴,s(气泡面 积)按population(人口)调整,因为气泡会存在重叠的情况,所以需要有一定的透明度 (alpha),避免因气泡叠加而看不到的情况,如图5-8所示。 84 图5-8 气泡图 可以看出谋杀率和入室盗窃率之间是呈正比关系的,但是人口多并不会造成犯罪率 的升高。此外,可以通过设置scatter命令中的c(颜色)参数,来展示四维图像。 全部代码如下。 import pandas as pd from matplotlib import pyplot as plt crime=pd.read_csv(r"http://datasets.flowingdata.com/crimeRatesByState2005. csv") crime=crime[1:] plt.scatter(crime["murder"],crime["burglary"],s= crime["population"]/40000, alpha=0.6) plt.xlim(0,11) plt.xlabel("Murder per 100,000 population") plt.ylabel("Burglary per 100,000 population") plt.title("Murder & Burglary") plt.show() 5.3 直 方 图 在统计学中,直方图(histogram)是一种对数据分布情况的图形表示,是一种二维统 计图表,它的两个坐标分别是统计样本和该样本对应的某个属性的度量,以长条图的形式 具体表现。因为直方图的长度及宽度很适合用来表现数量上的变化,所以较容易解读差 异小的数值。下面以图像直方图来说明其工作原理。我们熟悉的直方图更多的是作为图 像的后期工具,大多数人可能都只是用它来观察一张照片的曝光分布趋势,实际上直方图 可以挖掘的信息量非常庞大,许多照片细节都隐藏在直方图之中。 在图5-9中,横轴表示亮度,从左到右表示亮度从低到高。直方图的纵轴表示像素数 85 图5-9 图像直方图 量,从下到上表示像素从少到多。直方图在某个亮度区间的凸起越高,就表示在这个亮度 区间内的像素越多。比如这个直方图的凸起就主要集中在左侧,也就是说这张照片的亮 度整体偏低。 直方图是一个可以快速展示数据概率分布的工具,直观易于理解,并深受数据爱好者 的喜爱。Python中Matplotlib基于NumPy的histogram 进行了多样化的封装并提供了 完善的可视化功能。可以利用方法matplotlib.pyplot.hist(x,bins,color,label,alpha, orientation,rwidth)绘制直方图,下面解释一下常用的参数。 ① x:指定要绘制直方图的数据;输入值,这需要一个数组或者一个序列,不需要长 度相同的数组。 ② bins:指定直方图条形的个数。 ③color:设置直方图的填充色。 ④label:设置直方图的标签,可通过legend展示其图例。 ⑤alpha:透明度,浮点数。 ⑥ orientation:设置直方图的摆放方向,默认为垂直方向。 ⑦rwidth:设置直方图条形宽度的百分比。 从数学意义上来看,直方图是分箱到频数的一种映射,它可以用来估计变量的概率密 度函数。通过Python语言进行直方图绘制,首先利用numpy.random.laplace()从拉普拉 斯分布上提取出来浮点型样本数据。这个分布比标准正态分布拥有更宽的尾部,并有两 个描述参数(location=15和scale=3),由于这是一个连续型的分布,对于每个单独的浮 点值并不能做很好的标签。但我们可以将数据做分箱处理,然后统计每个箱内观察值的 数量,这就是真正的直方图所要做的工作。在x 轴上定义了分箱边界,y 轴是相对应的 频数,通过matplotlib.pyplot.hist()进行直方图绘制,用户无须手动定义分箱的数目,而 可以通过设置bins=a' uto'自动在写好的两个算法中择优选择并最终算出最适合的分箱 数。这里,算法的目的就是选择出一个合适的区间(箱)宽度,并生成一个最能代表数据的 直方图来,并获得返回值。n为数组或数组列表,表示直方图的值;bins为数组,返回各个 bin的区间范围;patches为列表的列表或列表(如图5-10所示)。 86 图5-10 Laplace直方图 完整代码如下。 import matplotlib.pyplot as plt import numpy as np #numpy 生成拉普拉斯分布,loc 偏移量15,scale 缩放3,产生数据量size 为500 d = np.random.laplace(loc=15, scale=3, size=500) n, bins, patches = plt.hist(x= d, bins= 'auto', color= '# 0504aa', alpha= 0.7, rwidth=0.85) plt.grid(axis='y', alpha=0.75) plt.xlabel('Value') plt.ylabel('Frequency') plt.title('Histogram') plt.text(23, 45, r'$\mu=15, b=3$') maxfreq = n.max() #设置y 轴的上限 plt.ylim(ymax=np.ceil(maxfreq / 10) * 10 if maxfreq %10 else maxfreq +10) plt.show() KDE(KernelDensityEstimation)为核密度估计,用于估计随机变量的概率密度函 数,可以将数据变得更平缓。利用Pandas库,通过plot.kde()创建一个核密度绘图,plot. kde()对于Series和DataFrame数据结构都适用。首先,我们先生成两个不同的正态分 布数据样本作为比较。在同一个Matplotlib轴上绘制每个直方图以及对应的KDE, Pandas中plot.kde()可以自动将所有列的直方图和KDE显示出来,十分方便(如图5-11 所示)。 87 图5-11 KDE直方图(1) 完整代码如下。 import matplotlib.pyplot as plt import numpy as np import pandas as pd means = 0, 10 stdevs = 3, 2 #生成两个正态分布数据 dist = pd.DataFrame( np.random.normal(loc=means, scale=stdevs, size=(1000, 2)), columns=['one', 'two']) fig, ax = plt.subplots() dist.plot.kde(ax=ax, legend=False, title='Histogram') dist.plot.hist(density=True, ax=ax) ax.set_ylabel('Probability') ax.grid(axis='y') ax.set_facecolor('#d8dcd6') plt.show() Seaborn是在Matplotlib 的基础上进一步封装的强大工具。对于直方图而言, Seaborn有distplot()方法可以将单变量分布的直方图和KDE同时绘制出来,使用十分 方便,distplot()方法默认绘制KDE,并提供fit参数,可以根据数据的实际情况自行选择 一个特殊的分布对应(如图5-12所示)。 完整代码如下。 import seaborn as sns import matplotlib.pyplot as plt import numpy as np 88 图5-12 KDE直方图(2) d = np.random.laplace(loc=15, scale=3, size=500) n, bins, patches = plt.hist(x= d, bins= 'auto', color= '# 0504aa', alpha= 0.7, rwidth=0.85) sns.distplot(d) plt.show() 5.4 练 习 练习题 1.散点图是对成组的( )数值进行比较,气泡图是对( )数值进行比较。 A.两个;两个B.两个;三个C.三个;两个D.四个;三个 2.作为电子商务企业,以下( )可以有效地提供不同商品的销售和趋势情况。 A.饼图B.分组直方图 C.气泡图D.条形图和折线图的组合图 3.简述散点图与气泡图有哪些相同点和不同点。 4.简述什么是直方图。