本文来自云栖社区官方钉群 "Python 技术进阶 http://tb.cn/UQkRRHw", 了解相关信息可以关注 "Python 技术进阶 http://tb.cn/UQkRRHw".
Matplotlib 是 Python 中最流行的绘图库, 它模仿 MATLAB 中的绘图风格, 提供了一整套与 MATLAB 相似的绘图 API, 通过 API, 我们可以轻松地绘制出高质量的图形.
1, 开场例子
我们以中国银行股票收盘价曲线作为例子来作为开场.
首先我们通过 pandas 导入数据, 并提取出收盘价一列:
- ChinaBank = pd.read_csv('data/ChinaBank.csv',index_col = 'Date')
- ChinaBank = ChinaBank.iloc[:,1:]
- ChinaBank.index = pd.to_datetime(ChinaBank.index)
- Close = ChinaBank.Close
我们来绘制 2014 年中国银行股票收盘价的走势图:
- plt.plot(Close['2014'])
- plt.show()
是不是很简单, 接下来, 我们一起去慢慢探秘 Matplotlib 的强大之处
2, 修改绘图属性
2.1 坐标
更改坐标范围
绘图时往往需要修改横纵坐标轴的范围, 以使曲线位于图形的中间位置:
- plt.plot([1,1,0,0,-1,0,1,1,-1])
- plt.show()
我们可以通过 ylim 方法修改 y 轴的范围, 比如我们想修改为(-1.5,1.5), 同理, 我们可以通过 xlim 方法来修改 x 轴的坐标范围:
- plt.plot([1,1,0,0,-1,0,1,1,-1])
- plt.ylim(-1.5,1.5)
- plt.show()
设定坐标轴标签和旋转
我们可以通过 xticks()和 yticks()函数设定坐标的标签, 两个函数主要有以下两个参数:
location: 指坐标的位置.
labels: 对应的坐标位置显示的标签.
两个参数一般是等长的数组, 该函数另一个常用的参数是 rotation 参数, 可以对坐标标签进行适当的旋转, 看下面的例子:
- plt.plot([1,1,0,0,-1,0,1,1,-1])
- plt.ylim(-1.5,1.5)
- plt.xticks(range(9),['02-01','02-02','02-03','02-04',
- '02-05','02-06','02-07','02-08','02-09'],rotation=45)
- plt.show()
可以看到 X 坐标由原来的数值 1,2,3 变成了我们设置的日期, 同时标签与 X 轴成 45 度角.
2.2 添加文本
添加标题
添加标题可以通过 title 函数来实现, 该函数主要有两个参数, 第一个是 str, 指明标题的内容, 第二个是 loc, 指明标题的位置, 可以选择 center,left 或者 right, 默认是 center
- plt.plot(Close['2014'])
- plt.title('中国银行 2014 年收盘价曲线',loc='right')
- plt.show()
可以看到, 在 Mac 的 Ipython 环境下, 中文是无法正常显示的, 我们可以通过下面的方法解决:
- from matplotlib.font_manager import FontManager, FontProperties
- def getChineseFont():
- return FontProperties(fname='/System/Library/Fonts/PingFang.ttc')
- plt.plot(Close['2014'])
- plt.title('中国银行 2014 年收盘价曲线',loc='right',fontproperties=getChineseFont())
- plt.show()
设置坐标轴标签
设置坐标轴标签可以通过 xlabel 和 ylabel 函数来实现
- plt.plot(Close['2014'])
- plt.title('中国银行 2014 年收盘价曲线',loc='center',fontproperties=getChineseFont())
- plt.xlabel('日期',fontproperties=getChineseFont())
- plt.ylabel('收盘价',fontproperties=getChineseFont())
- plt.show()
增加图形背景 grid
绘图时常常会在图形背景中增添方格, 以便于人们更直观地读取线条中点的坐标取值以及线条整体的分布范围. 可以使用 grid 函数增加和设定图形的背景.
函数原型: matplotlib.pyplot.grid(b=None,which='major',axis='both',**kwargs)
参数 b, 设定是否显示 grid, 如果要显示 grid, 将 b 参数设置为 True, 参数 which, 设定坐标轴的分割标示线的类型, 取值为 major,minor 或者 both, 默认为 major, 表示以原本的坐标轴分割标示线为准; 若取值为 minor, 则进一步细分坐标轴分割标示线, 但是分割标准要提前设定, 如果只是设定值为 minor, 则 grid 不会显示; both 表示大小区间坐标轴分割线都有, 参数 axis, 指定绘制 grid 的坐标轴, 取值为 both,x 或 y.
- plt.plot(Close['2014'])
- plt.title('中国银行 2014 年收盘价曲线',loc='center',fontproperties=getChineseFont())
- plt.xlabel('日期',fontproperties=getChineseFont())
- plt.ylabel('收盘价',fontproperties=getChineseFont())
- plt.grid(True,axis='y')
- plt.show()
增加图例
当多条曲线显示在同一张图中时, 图例可以帮助我们区分识别不同的曲线, 在中国银行的数据中, 我们可以把开盘价和收盘价同时放在一张曲线图中, 并为二者增加图例.
增加图例使用 legend()函数, legend 函数中最常见的一个参数是 loc 参数, 表示图例在图中显示的位置, 我们一般设置为 best 就好, 表示在图中最适宜的位置显示图例成功增加图例的前提是在绘图时提供 label 属性值, label 属性值就是图例上的文本, 同时我们还要注意中文显示的问题.
- Open=ChinaBank.Open
- plt.plot(Close['2014'],label='收盘价')
- plt.plot(Open['2014'],label='开盘价')
- plt.legend(loc='best',prop=getChineseFont())
- plt.show()
2.3 多种线条属性
线条的类型
在绘制曲线时, 除了绘制实线外, 还可以绘制虚线, plot 函数中的 linestyle 参数用于设置曲线类型, 为了书写方便, 有时候用 ls 代替 linestyle. 有如下的常见取值
- plt.plot(Close['2014'],label='收盘价',linestyle='solid')
- plt.plot(Open['2014'],label='开盘价',ls='-.')
- plt.legend(loc='best',prop=getChineseFont())
- plt.xlabel('日期',fontproperties=getChineseFont())
- plt.ylabel('收盘价',fontproperties=getChineseFont())
- plt.title('中国银行 2014 年收盘价曲线',loc='center',fontproperties=getChineseFont())
- plt.grid(True,axis='y')
- plt.show()
图形的颜色
修改图形的颜色通过 plot 函数中的 color 参数来设置, 也可以简写成 c, 最常用的颜色指定方式是指定颜色的名称或者简写, 也可以通过 RGB 数组来设置.
- plt.plot(Close['2014'],label='收盘价',c='r',linestyle='solid')
- plt.plot(Open['2014'],label='开盘价',c='b',ls=':')
- plt.legend(loc='best',prop=getChineseFont())
- plt.xlabel('日期',fontproperties=getChineseFont())
- plt.ylabel('收盘价',fontproperties=getChineseFont())
- plt.title('中国银行 2014 年收盘价曲线',loc='center',fontproperties=getChineseFont())
- plt.grid(True,axis='y')
- plt.show()
点的形状类型
除了设置线条类型外, 还可以设置数据点的形状, 图形的形状通过 marker 参数来设置. marker 参数主要有下面的取值:
- plt.plot(Close['2014'],label='收盘价',c='r',marker='o',linestyle='solid')
- plt.plot(Open['2014'],label='开盘价',c='b',marker='v',ls='-.')
- plt.legend(loc='best',prop=getChineseFont())
- plt.xlabel('日期',fontproperties=getChineseFont())
- plt.ylabel('收盘价',fontproperties=getChineseFont())
- plt.title('中国银行 2014 年收盘价曲线',loc='center',fontproperties=getChineseFont())
- plt.grid(True,axis='y')
- plt.show()
线条宽度
线条宽度可以通过 plot 函数中的 linewidth 函数指定, 也可简写为 lw
- plt.plot(Close['2014'],label='收盘价',c='r',marker='o',linestyle='solid',linewidth=1)
- plt.plot(Open['2014'],label='开盘价',c='b',marker='>',ls='-.',lw=3)
- plt.legend(loc='best',prop=getChineseFont())
- plt.xlabel('日期',fontproperties=getChineseFont())
- plt.ylabel('收盘价',fontproperties=getChineseFont())
- plt.title('中国银行 2014 年收盘价曲线',loc='center',fontproperties=getChineseFont())
- plt.grid(True,axis='y')
- plt.show()
前面讲到的线条的类型, 图形的颜色和点的形状类型, 可以合为一个属性, 使用他们的符号取值将其拼接, 这个参数的位置是有限制的, 比如在下面的代码中, 它只能放在 label 前面, 在 label 参数后面则会报错.
- plt.plot(Close['2014'],'--rD',label='收盘价',linewidth=1)
- plt.plot(Open['2014'],'--b>',label='开盘价',lw=3)
- plt.legend(loc='best',prop=getChineseFont())
- plt.xlabel('日期',fontproperties=getChineseFont())
- plt.ylabel('收盘价',fontproperties=getChineseFont())
- plt.title('中国银行 2014 年收盘价曲线',loc='center',fontproperties=getChineseFont())
- plt.grid(True,axis='y')
- plt.show()
3, 常见图形绘制
3.1 柱状图
在刚才的收盘价数据中, 统计收盘价落在 (2,3],(3,4],(4,5],(5,6] 的天数, 分别有 228,35,81,1 天, 我们来绘制柱状图:
plt.bar(left=[2,3,4,5],height=[228,35,81,1],bottom=2,width=1,color='r',edgecolor='b')
使用 barh 函数可以绘制水平柱状图:
plt.barh([2,3,4,5],[228,35,81,1],height=1.0,color='r',edgecolor='b')
3.2 直方图
柱状图主要用于展示定性数据的分布, 对于定量数据的分布, 一般使用直方图来呈现. 绘制直方图用 pyplot 包中的 hist 函数来实现, 主要有以下几个参数:
bins 用于设置直方图分布区间的个数;
range 用于设置直方图的小矩形的最小值与最大值;
orientation 用于设置直方图的水平或者垂直显示, 默认是竖直的直方图, 可以将 orientation 设置为 horizontal 使其变为水平直方图.
plt.hist(Close,bins=12)
plt.hist(Close,bins=12,orientation='horizontal')
也可以绘制累积分布直方图, 将参数 cumulative 设置为 True 即可:
plt.hist(Close,range=(2.3,5.5),orientation='vertical',cumulative=True,color='r',edgecolor='b')
3.3 饼图
绘制饼图使用 pie 方法, 主要参数有:
labels: 用于设置扇形图的标签
colors: 用于设置扇形图的颜色
shadow: 用于设定扇形图是否有阴影
- plt.pie([228,35,81,1],labels=('(2,3]','(3,4]',
- '(4,5]','(5,6]'),colors=('b','g','r','c'),shadow=True)
3.4 箱线图
箱线图也是在分析数据时经常用到的一种图形, 正如其名, 箱线图由一个矩形和两条线组成, 矩形的上边和下边分别是变量的上下四分位数, 中间的一条线表示数变量的中位数. 在矩形的上下两边各延伸出一条线, 每条线的长度一般为 1.5 倍的四分位距(上下四分位数之差), 这两条线被视为异常值截断线, 上端的线为上边缘线, 下端的线为下边缘线, 在线的外面可能还会有一些点, 这些点一般会被认为是异常值. 箱线图能够很直观地表示出一个变量的分布, 也有助于检测异常值.
pyplot 的 boxplot 函数用于绘制箱线图, 主要有以下几个参数:
notch: 表示箱线图的类型, 默认为 False, 即绘制矩形箱线图, 如果取值为 True, 表示绘制锯齿状箱线图
labels: 表示箱形图的标签, 一般为字符串序列类型
- import numpy as np
- prcData = ChinaBank.iloc[:,:4]
- data = np.array(prcData)
- plt.boxplot(data,labels=('Open','High','Low','Close'))
- plt.title('中国银行股票箱线图',fontproperties=getChineseFont())
4, 多图绘制
除了上面介绍的, Matplotlib 的另一大特色是面向对象的绘图, 类比生活中的用纸笔绘图, 我们来解释 Matplotlib 面向对象绘图
在使用生活中纸笔画图时, 我们需要先找到一张白纸, 在白纸上绘图. 对于 Matplotlib 来说, 绘图之前需要先创建一个 Figure 对象, Figure 对象是一个空白区域, 然后我们就可以在上面进行绘图. Figure 对象可通过 pyplot 包中的 figure 函数来创建.
fig = plt.figure(1)
在这张白纸上, 我们可以选择较大区域, 指画一个收盘价折线图, 如果想要节约用纸或者对比两个价格序列, 可以将这个纸
分成两个区域, 分别绘制收盘价折线图和开盘价折线图. 在 Matplotlib 绘图中, 每个 Figure 对象可以包含一个或者几个 Axes 对象. 每个 Axes 对象即一个绘图区域, 拥有自己独立的坐标系统, 假设我们现在需要两个区域, 分别绘制中国银行股票的开盘价走势和收盘价走势, 我们可以创建两个 Axes 对象.
- ax1 = fig.add_axes([0.1,0.1,0.3,0.3])
- ax2 = fig.add_axes([0.5,0.5,0.4,0.4])
可以看到在创建 Axes 对象时传入了一个数值型 list,list 的前两个元素决定了 Axes 的左下角坐标, 而第三个和第四个参数决定了 Axes 的长和宽接下来, 我们基本就可以按照之前介绍的知识进行绘图了:
- fig = plt.figure(1)
- ax1 = fig.add_axes([0.1,0.1,0.3,0.3])
- ax2 = fig.add_axes([0.5,0.5,0.4,0.4])
- ax1.plot(Close[:10])
- ax1.set_title('前十个交易日收盘价',fontproperties=getChineseFont())
- ax1.set_xlabel('日期',fontproperties=getChineseFont())
- ax1.set_ylabel('收盘价',fontproperties=getChineseFont())
- ax1.set_ylim(2.4,2.65)
- ax2.plot(Open[:10])
- ax2.set_title('前十个交易日开盘价',fontproperties=getChineseFont())
- ax2.set_xlabel('日期',fontproperties=getChineseFont())
- ax2.set_ylabel('开盘价',fontproperties=getChineseFont())
- ax2.set_ylim(2.4,2.65)
- plt.show()
在实际绘图中, 如果一个 Figure 对象中包含多个 Axes 对象, 每个 Axes 对象的位置除了通过区域坐标和长度来设定一位, 更为常用的方式是通过子图 subplot()函数来设定.
- fig = plt.figure()
- ax1 = plt.subplot(221)
- ax2 = plt.subplot(222)
- ax3 = plt.subplot(223)
- ax4 = plt.subplot(224)
- plt.show()
参数 221 中的 22 表示子图排列为 2*2 形式, 1 表示第一个子图, 其他均为同样的道理.
最后, 我们再来体验一个绘制多图的例子:
- Close15 = Close['2015']
- ax1 = plt.subplot(221)
- ax1.plot(Close15,color='k')
- ax1.set_xlabel('日期',fontproperties=getChineseFont())
- ax1.set_ylabel('收盘价',fontproperties=getChineseFont())
- ax1.set_title('中国银行 2015 年收盘价曲线',fontproperties=getChineseFont())
- Volume15 = ChinaBank['Volume']['2015']
- Open15 = Open['2015']
- ax2 = plt.subplot(212)
- left1 = Volume15.index[Close15>=Open15]
- hight1 = Volume15[left1]
- ax2.bar(left1,hight1,color='r')
- left2 = Volume15.index[Close15<Open15]
- hight2 = Volume15[left2]
- ax2.bar(left2,hight2,color='g')
- ax2.set_ylabel('成交量')
- ax2.set_title('中国银行 2015 年成交量柱状图')
- plt.show()
来源: https://yq.aliyun.com/articles/691459