赞助

机器学习-数据可视化

现在每天产生的数据都是海量的,这些数据中既有高质量的也有很多垃圾,如何从这些海量的数据中洞察出这些数据的内在联系是我们机器学习的核心内容。如果光把数据丢在大家的面前,咱们肯定是无感的,无法获取这些数据的意义。为了能够更加直观的了解这些数据的一些特征,例如数据的分布情况,数据的趋势和走势,数据之间的对比等等。这些特性可以很好的帮助我们理解一些数据的内在特性,从而对我们的特征工程也有很大的辅助功能。还有最大的一个功能就是帮助咱们做很多看起来很牛逼图像,然后在报告上面装B(大家都懂的,嘘嘘嘘嘘)。在数据科学的领域中,比较底层的数据可视化组件事matplotlib. 但是鉴于上一节咱们已经说过pandas,pandas的可视化接口也都是基于matplotlib的,但是pandas的更加抽象,所以运用起来也更加简单一点。另外我也会简单的介绍一款专门用于数据可视化的组件叫做seaborn,它也是基于matplotlib的,但是seaborn也更加抽象,level也更加高,在可视化方面提供的接口也更加简单丰富。具体要用哪一个都一样,大家随便选择,只要大家能在PPT或者报告中能成功在老板面前把B装起来,咱们就成功了,不管黑猫白猫,能抓住老鼠的就是好猫。哈哈,那咱们就开始咱们的表演吧。

  • categorical data type plot (univarate bar chart)

首先咱们先要了解category data是什么,category data通常也分两种:nominal category和ordinal category。nominal category通常是一些名词,然后对于这些category的顺序并不care,例如省份,国家,品牌等等(地域黑除外,哈哈);ordinal category通常是一些对于顺序很敏感的变量,然后对于趋势和分布比较重要的数据,例如:分数,月份,年份,人口,消费等等啦。对于category data通常的可视化操作都是bar chart 或者 pie chart.下面的主要以bar chart作为例子来解释。本文主要是讲述数据的可视化,默认咱们已经加载的数据哈,具体加载数据的过程,下面的代码就不展示了。看下面的bar chart实例,然后我来解释细节

reviews.points.value_counts().plot.bar()#sorting value from max to min(default)
reviews.points.value_counts().sort_index().plot.bar()#sorting index from min to max (can see the trend)

由于value_counts()返回的是一个series,并且返回的series的排序是按照这个series的value值从大到小的顺序,所以plot的结果就是只有一个变量,就是这个series的index,那么这个变量对应的值就是这个series的value值。第一句代码的图像结果如下:

 

从上图可以看出,上图的变量是乱序的,纵坐标(value)是按照从大到小的顺序的。 上面的第二句代码多了一句sort_index(), 直译过来就是将原来series的index 排序了,那么新的series的index是按照从小到大的顺序排列的。它的结果如下:

 

 从上图可以很清晰的看出数据的分布情况,第二幅图也能给我们更加重要的数据信息。

补充:对于ordinal category的数据,咱们还有一种常用的绘图方式,那就是hist()。hist()能自动将series中的index进行排序,然后分成N个bins,每个bins 对应的纵坐标则是这个bin相对应的frequency(即出现的次数)。例如下面的代码和图片

reviews.points.plot.hist()

 

 从上面的代码和图片可以看出,hist()函数不需要将现将points进行value_counts进行计算,它可以直接自动将series中的value按照顺序分成N个bins,然后自动计算在每个bin中的数量。从上面的代码可以看出,bar()是讲series中的index作为变量,而hist()是将series中的value作为变量,而frequency(即出现的次数)作为y. 这一点在初学者中经常弄混淆,甚至认为两者是一样的。其实两者是有本质区别的,bar()是从series中一条一条的取数据,然后分别将index和value作为x,y进行绘制;而hist()则是一条一条的在series中取数据,只将series中的value作为x, 然后一直count每一个x。这两种plot都是统计series中的value出现的次数,另外,无论hist()还是bar(),series的value必须是numerical,不能是categorical。

有的时候,另外一种图也能很好的反映index和value之间的关系,那就是line chart。这种图片也能非常好的反映数据的趋势,所以一般也是用在ordinal的category中。如下

reviews.points.value_counts().sort_index().plot.line()

 

  •  Biavariate

在很多情况下,咱们会遇到要展示2个自变量的图片。例如经纬度,bmi等等。通常这种情况下,这种图都是反映的是出现的频率,热度等。通常展现两个自变量的图有scatter,hexbin.好了,下面咱们就直接上代码和结果给大家解释一下

reviews[reviews.price<100].sample(100).plot.scatter(x='price',y='points')

 

 上面就是scatter图的代码和结果,咱们可以啃方便的看出数据的分布情况,不同于bar chart和histogram 它们都是展现一个维度的数据分布情况, scatter是展示的2个维度的数据分布情况。但是他有个致命的弱点,就是数据特别多并且它们很多的值都一样的时候,它们是覆盖在一起的,咱们就无法用眼睛直观的准确的分辨出它们的分布情况了。scatter适合那些数据不是特别多,并且重复数据很少的情况。那么咱们怎么解决这些问题呢?答案就是hexbin图啦,前人已经帮咱们把坑都填好啦,哈哈,下面咱们看看hexbin是如何展现2个变量的分布情况吧

#another plot method - Hex plot could perfectly deal with the scatter plot's drawbacks. Hex aggregatepoints in
#a hexagons, and the colors of the hexagons represent the values within them, which clearly conveys the meaningful
#results and view to us, such as: where does the examples cluster. in this case, it clusters around 87.5points and around 20 dollars
reviews[reviews.price<100].plot.hexbin(x='price',y='points',gridsize=15)

 

 上面的的注释已经讲得很清楚啦,hexbin图中,颜色越深,出现的次数就越多。这样咱们就不怕数据重叠的问题啦,非常直观的就可以看出数据的分布情况。综上所述,当然啦,对于bivariate的数据可视化肯定还有很多其他的API,不可能全在这讲完,对于一名合格的程序员,咱们最重要的品质就是看文档的能力,具体咱们看,你们直接去pandas的官网看哈。总之对于数据量不大,重复数据不多的情况,咱们可以选择scatter,对于数据量很大,并且很多重复数据的时候,就选hexbin,可以更加简单的看到数据的分布情况。

  • Subplotting

大家很多时候一定遇到过在同一个画布上面同时画出好几个图片的需求,可能用于对比,可能用于展示更加丰富的信息。这种时候,咱们就想起了subplot了。下面先通过一个简单的实例展示一个最简单的subplot

fig,axarr = plt.subplots(2,2,figsize=(12,8))
first_150_reviews['points'].value_counts().sort_index().plot.bar(ax=axarr[0][0])
first_150_reviews['price'].value_counts().plot.hist(ax=axarr[0][1])
first_150_reviews['variety'].value_counts().head(20).plot.bar(ax=axarr[1][0])
first_150_reviews['province'].value_counts().head(20).plot.bar(ax=axarr[1][1])

 

 

上面的代码展示了一个subplot的最简单的方式,首先第一个参数是(2,2)代表着是有几个subplot,第二个参数figsize代表着整个画布的大小,所以第一行代码是初始化一个画布,并且设定一些画布的初始值。后面的四行代码则是绘图的过程,每一行的参数ax代表着坐标系,ax后面的index分别对应着subplot的row和column,例如ax[0][1]代表着第一行第二列。所以大家看看subplot是不是可以展现出更加丰富的内容呢。当然啦,每一个subplot ax[row][column] 也可以有一些个性化的设置,这个咱们后面慢慢说,上面只是一个最最最最简单的绘画subplot的一种方法。

  • 图片个性化

当然啦,既然是图嘛,免不了很多时候咱们想着要美化一下下嘛,毕竟经常要给别人展示的,门面还是很重要的。所以咱们经常需要将图形进行一些个性化设置,例如图形的颜色,字体大小,图形标题,图形大小等等一系列的特性。首先咱们看一下图形的大小哈,咱们可以通过figsize的参数进行设定,如下

reviews.points.value_counts().sort_index().plot.bar(figsize=(20,6))

可以通过设置tuple里面的数据对图片的大小进行设置。接下来咱们可以看看对图形颜色的设置

#customerize the color of the bars
reviews.points.value_counts().sort_index().plot.bar(figsize = (12,6), color = 'green')

上面代码就是将bar chart中的bar设置成绿色。接下来咱们瞧一瞧坐标系上字体大小的设置

#coustomerize font
reviews.points.value_counts().sort_index().plot.bar(figsize = (12,6), color = 'red', fontsize = 20)

上面代码的fontsize可以设置坐标系字体的大小。最后咱们来看看图形标题的设置

reviews.points.value_counts().sort_index().plot.bar(
        figsize=(12,6),
        color='green', 
        fontsize = 16, 
        title='Rankings Given By Wine Magazine'
        )

上面的代码可以给这个图片设置一个标题叫做“Rankings Given By Wine Magazine”,这里咱们有个小细节需要注意一下就是标题的字体大小也可以设置,但是在pandas plot的框架上面没法设置,必须去更加底层的matplotlib去设置图片标题的字体大小,代码如下

import matplotlib.pyplot as plt
title_customerise_plot = reviews.points.value_counts().sort_index().plot.bar(
        figsize = (12,6),
        color = 'green',
        fontsize = 16
        )
title_customerise_plot.set_title("Ranking Given By Wine Magazine",fontsize = 20)

咱们必须通过matplotlib.pyplot中的set_title()的方法来设置图片标题的大小,而无法直接在pandas中设置它。上面的结果如下

 

  • Seaborn 简介

数据的可视化呢,除了pandas提供一些简单易用的API之外,还有一个专门用于数据可视化的框架,那就是seaborn。它也是基于matplotlib的,但是用起来比matplotlib简单,功能也比pandas的绘图功能更加丰富,毕竟seaborn人家是专业的嘛,哈哈。关于seaborn我也就在这里简单的演示一下bar chart,line chart,scatter plot, kde 等等一些简单的应用哈。还是那句话,关于绘图有无数个API,需要大家安静下来去seaborn的documentation细细品味,嘻嘻. 下面的代码分别展示了bar chart,line chart在seaborn中的应用

import matplotlib.pyplot as plt
import seaborn as sns
#data flight_delays
= pd.read_csv("C:\\Users\\tangx\\OneDrive\\Desktop\\DATA\\flight_delays.csv",index_col='Month',parse_dates = True) spotify_df = pd.read_csv("C:\\Users\\tangx\\OneDrive\\Desktop\\DATA\\spotify.csv",index_col="Date",parse_dates = True) #plotting
sns.lineplot(data
=spotify_df['Despacito'],label = "Despacito") sns.barplot(x=flight_delays.index,y= flight_delays.NK)

从上面的代码可以看出,series都是作为参数(数据源)传递给函数的,而不像在pandas绘图那样,将绘图的方法作为series的方法。seaborn中也可以传递很多的参数来个性化图形,例如上面的label。大家有兴趣可以自己去看看哈。上面的结果如下

 

 咱们可以从上图看出,对于数据源咱们既可以直接把series传给data参数,也可以分别将横坐标纵坐标的值分别传递给x,y。而且如果你选择第二种它还能自动给横坐标和纵坐标命名,还挺智能。seaborn还有更加牛的功能,看看下面两个个scatter plot,你去瞧一瞧那些牛逼的功能

sns.scatterplot(x=insurance.bmi,y=insurance.charges)
sns.scatterplot(x=insurance.bmi,y=insurance.charges,hue=insurance.smoker)

 

通过上面咱们可以看出,虽然是同一个scatter,但是它还可以通过hue这个参数,将数据根据一定的条件(例如上面的是不是吸烟者)来分开,从而可以帮助咱们更加深刻的理解数据。如果看到这里你们就觉得seaborn牛逼,那么只能说你们还是太年轻,哈哈,它还是有大招的,那就是它还可以话拟合线,具体是什么呢?看看下面的代码

sns.regplot(x=insurance['bmi'], y=insurance['charges'])
sns.lmplot(x='bmi',y='charges',hue='smoker',data=insurance)

 

 

 regplot相当于直接画一条regression line,而lmplot则能够根据不同条件下的子集画出不同的regression line,这对于咱们分析数据走势,和一些数据的subset的趋势都有很大的帮助。最后咱们来看看seaborn的另外一个大杀器,那就是KDE plot, 那么很大同学可能会有疑问了,什么是kde呢? kde其实是kernel density estimation的简称,它其实是一种概率分布的技术,像是一个小window从咱们的图形从左到右的走一遍,然后把那些偏离很大的值(outliers)和那些突然变化很大的值(in-between values)删除和变成一条更加顺滑的线,并且将结果转成概率。它既可以用于univariate也可以用于bivariate。注意:kde的y值(函数的变量)是概率(对于2d数据来说,是通过颜色的深浅来判断的),而不是frequency!!!!!!!。那咱们现在来看看kde的简单应用

first_150_reviews[first_150_reviews['price']<200]['price'].value_counts().sort_index().plot.line()
sns.kdeplot(first_150_reviews.query('price<200').price)

 

 咱们看看上面的两个图片,右边的图片应用了kde,是不是像给第一幅图用了海飞丝一样,瞬间顺滑了很多,也更加直观的展示了数据的分布和趋势。下面咱们来看看kde用于bivariate的情况

first_150_reviews[first_150_reviews.price<200][['price','points']].dropna().sample(5000).sort_index().plot.scatter(x='price',y='points')
sns.kdeplot(first_150_reviews[first_150_reviews.price<200][['price','points']].dropna().sample(5000))

 

 第一个图片是一般的scatter,第二幅图是kde,越靠近图形中间的位置,出现的概率越大。 至于哪一个好,那一牛逼,你们自己心里有一把尺,不用我说了吧。哈哈

  •  box plot and violin plot

现在介绍最后一种常见的图形,其实是两种图,但是他们本质一样,分别是box plot和violin plot。咱们先看创建它们的代码和运行结果然后在分析这两种图形

df = first_150_reviews[first_150_reviews.variety.isin(first_150_reviews.variety.value_counts().head(5).index)]
sns.boxplot(
        x="variety",
        y = "points",
        data = df
        )


#violin plot
#violin plot cleverly replace the box in the boxplot with a kde for the data, it is more visually enticing
sns.violinplot(
        x='variety',
        y='points',
        data = df)

 

看到上面的五颜六色的图形,是不是心里一万只曹尼玛,哈哈,心想什么玩意儿。待我慢慢来分析,首先看看左边的图形box plot,最下面的一条线是每一个variaty相对应points的最小值,中间box有三条横线,分别对应着该variaty下面points的25%,median,75%的值,然后box上面的最顶上的一个横线代表着该variaty下points的最大值。右边的violin plot其实就是对box plot的kde,更能反映出数据的分布情况。他们之间的对比可以看下面这个经典的图

 

 

总结:这节的数据可视化的内容很杂,其实如果想把数据可视化玩的转,最重要的的捷径就是理解数据。关于可视化的API我个人认为是最简单的API,而且不多,建议大家都能理解透彻。虽然可视化的内容不难,但是有很多图形很像,但是要知道他们的不同,例如bar chart 和histogram,box plot和violin plot 等等,虽然看着相似,但其实是不同的。就像开头说的,这里主要是写的是pandas和seaborn的可视化的方法,实际中还经常需要用到底层一点的matplotlib,这里我就不细说了,如果上面的内容能消化,以大家的能力看matplotlib的API 应该也不是问题的。

posted @ 2020-01-15 20:31  HappyPuppy  阅读(2556)  评论(0编辑  收藏  举报