首先py的画图都是
xx.plot(kind=’xx’)的形式
这个和R的ggplot后面的geom_xxx比较类似。
但是py弱在图形的整合,例如ggplot里面有个stat,可以直接很方便的进行count,identity等操作,而py的数据集需要喂好了给matplot,不过这样也倒是省时,因为py的groupby本来就不算很麻烦(和R的datatable差不多)。
下面进行柱状图的绘制:
iris.groupby('Species')['Sepal.Length'].sum().plot(kind='bar',
title='Bar',
color='k')
这个相当于R的geom_bar(stat=’count’)
需要首先groupby Species,然后加总Sepal.Length,最后画一个柱状图,Color=K 就是黑色,如图:
同样的,可以用均值加总:
iris.groupby('Species')['Sepal.Length'].mean().plot(kind='bar',
title='Bar-mean',
color='b')
当然可以放两个柱状图一起:
iris.groupby('Species')['Sepal.Length',
'Sepal.Width'].sum().plot(kind='bar',
title='combinebar',
color='by')
这个color就是b和y,中间也没有间隔,这个和R倒是不太一样;
当然,也可以都放上,并旋转坐标轴的标签:
iris.groupby('Species').sum().plot(kind='bar',
title='Identitybar',
rot=1)
其中的rot=1 ,就是旋转xtick
也可以堆叠:
iris.groupby('Species').sum().plot(kind='bar',
title='Stackbar',
stacked=True)
当然可以旋转成水平,通过kind=barh
iris.groupby('Species').sum().plot(kind='barh',
title='h-bar',
stacked=True)
然后如果是做百分比柱状图,首先柱状图这部分是帮不了了,只能求助于数据整形;
而数据整形的话,需要把三个种类,整成百分比的样子;这个略微有点技巧;首先既然是百分比,那么需要汇总值,先看下
iris.groupby('Species').sum()
结果为:
Sepal.Length Sepal.Width Petal.Length Petal.Width
Species
setosa 250.3 171.4 73.1 12.3
versicolor 296.8 138.5 213.0 66.3
virginica 329.4 148.7 277.6 101.3
这三个种类的汇总值在这,同时,需要用每一个种类去除三个种类加总的值,而三个种类加总的值为:
iris.iloc[:,0:4].sum()
结果为:
Sepal.Length 876.5
Sepal.Width 458.6
Petal.Length 563.7
Petal.Width 179.9
dtype: float64
可以看到加总值是个Series,而分类汇总是个Dataframe,而Dataframe的列就是Series的index,所以需要用dataframe去除series,直接用/也可以,或者用以下代码:
iris.groupby('Species').sum().div(iris.iloc[:,0:4].sum())
看到结果是:
Sepal.Length Sepal.Width Petal.Length Petal.Width
Species
setosa 0.285568 0.373746 0.129679 0.068371
versicolor 0.338620 0.302006 0.377861 0.368538
virginica 0.375813 0.324248 0.492461 0.563091
但是到这里还不行,因为行列需要翻转下,因为需要把类别作为行,也就是x轴,然后画图,整体代码就是:
iris.groupby('Species').sum().\
div(iris.iloc[:,0:4].sum()).T.\
plot(kind='bar',
title='prop',
stacked=True,
rot=1).\
legend(loc=1) #旋转坐标轴图例位置
后面的stacked就是堆叠,rot=1是旋转xticks,legend(loc=1)是调整图例位置,得到的图形为:
总结下,柱状图原理很简单,就是data.plot(kind=’bar),其他的复杂逻辑都在数据整形中,python柱状图和excel的画图比较类似,都是使用宽格式,这个和ggplot有典型的区别,因为ggplot只接受长格式的画图,总的对比,py的图形更符合常理,但是操作起来较为繁琐。
下面看下直方图。
基本直方图很简单:
iris['Sepal.Length'].plot(kind='hist',
color='k',
title='Hist')
但是正常情况下,都会看几个数据分布的差异,也就用到了复合的直方图:
iris.loc[:,{'Sepal.Width','Petal.Length'}].plot(kind='hist',
alpha=0.5,
title='MultiHist')
其中alpha和ggplot参数类似,都是调整透明度。
除此之外,还有一种特殊的直方图,是累计直方图,累计直方图和累计密度图类似,把数据从小到大加到100%:
iris.loc[:,{'Sepal.Width','Petal.Length'}].plot(kind='hist',
alpha=0.5,
cumulative=True,
title='Cum-Hist')
当然,有的时候需要一张图中展示很多直方图(或者其他图),就类似ggplot的facet,分面。具体的代码为:
iris.iloc[:,:4].plot(subplots=True,
layout=(2,2),
kind='hist',
title={'1','2','3','4'})
其中subplots=True的意思是画一个subplot,然后layout就是这个画布的数量,当然kind就是种类。还有一个特征就是TITLE,从图形上看,title是从左下角作为1,然后一个逆时针转到4的:
最后一个直方图是横向的直方图:
iris['Sepal.Length'].hist(color='k',orientation='horizontal')
有直方图就有密度图,在ggplot中,只要输入stat=density就是一个密度图了,而python这一点也很简单,但是,需要scipy包的支持
这一点让我蛋疼了好久,因为从pycharm里找不到适合py3.6的scipy包,只能从非官网上下载whl:
http://www.lfd.uci.edu/~gohlke/pythonlibs/#numpy
需要下载一个适合python版本的.whl的numpy和scipy:
我的是:
numpy‑1.13.1+mkl‑cp36‑cp36m‑win32.whl
scipy‑0.19.1‑cp36‑cp36m‑win32.whl
下载完成后,需要再命令行(没错,就是ms-dos的命令行)用cd转移环境变量到python下scripts的目录,比如我的就是:
cd C:\\Users\\yangyunru\\AppData\\Local\\Programs\\Python\\Python36-32\\scipts
在这个目录下,把刚才下载的两个whl文件拖到scripts目录下,然后命令行中输入:
pip install numpy‑1.13.1+mkl‑cp36‑cp36m‑win32.whl
pip install scipy‑0.19.1‑cp36‑cp36m‑win32.whl
然后才可以使用scipy,也就是才可以画密度图;
密度图原理也很简单,直接输入:
iris['Sepal.Length'].plot(kind='kde',
title='Density')
就可以得到:
同时,一张图中多个density图:
iris.loc[:,{'Sepal.Width','Petal.Length'}].plot(kind='kde',
title='Multidensity')
当然,也可以分面做密度图
fig=plt.figure() #画布
fig,axe=plt.subplots(1,2,sharey=True) #共用Y轴
iris['Sepal.Width'].plot(kind='kde',
ax=axe[0],
title='Sepal.Width') #第一个画Sepal.Width
iris['Sepal.Length'].plot(kind='kde',
ax=axe[1],
title='Sepal.Length') #第二个画Sepal.Length
图形为:
其中sharey=True就是两个共用一个Y轴,更能看出差异;
本章最后一个图形介绍下箱线图:
简单的箱线图就是:
iris.plot(kind='box',
title='Boxplot')
如果觉得图形有点丑,改变下参数:
boxcolor=dict(boxes='DarkGreen',
whiskers='DarkOrange',
medians='DarkBlue',
caps='Gray')
iris.plot(kind='box',
color=boxcolor,
sym='r+',
title='Colored-Boxplot') #sym就是异常值的处理,异常值可以认为是长尾
针对sym这个需要说明下,也就是异常值,上面的小点点或十字;引用百科说法:
在Q3+1.5IQR(四分位距)和Q1-1.5IQR处画两条与中位线一样的线段,这两条线段为异常值截断点,称其为内限;在Q3+3IQR和Q1-3IQR处画两条线段,称其为外限。处于内限以外位置的点表示的数据都是异常值,其中在内限与外限之间的异常值为温和的异常值(mild outliers),在外限以外的为极端的异常值(li)的异常值extreme outliers。
http://wiki.mbalib.com/wiki/%E7%AE%B1%E7%BA%BF%E5%9B%BE
也就是在三分位数+1.5倍的四分位距,其中
四分位距=Q3-Q1
那么超出Q3+1.5(Q3-Q1)都是异常值,同理,Q1-1.5(Q3-Q1)也是异常值。
在看几个箱线图的特例:水平箱线图:
iris.plot(kind='box',
color=boxcolor,
vert=False,
title='H-box') #sym就是异常值的处理
下面以分组箱线图结束本章:
分组箱线图个人认为是比较常用的图形,可以很明显的看到各个指标的差异,而分组就是按照Species分组了。
首先既然是分组,就需要重塑数据集,然后填充到每一个画布中:
Versicolor=iris.loc[iris['Species']=='versicolor']
Virginica=iris.loc[iris['Species']=='virginica']
Setosa=iris.loc[iris['Species']=='setosa']
fig=plt.figure()
fig,axe=plt.subplots(1,3,sharey=True)
Versicolor.plot(kind='box',ax=axe[0],title='Versicolor')
Virginica.plot(kind='box',ax=axe[1],title='Virginica')
Setosa.plot(kind='box',ax=axe[2],title='Setosa')
前面是设定三个数据集,这三个数据集都是从iris中抽取出来的,分别对应三个种类;然后设定fig画布,并且设定axe,也就是subplot个数,这里是三个;然后分别进行画图,在ax中设定画在aex的哪里,图形如下: