掌握好初级的可视化,能够在数据分析的过程中利用可视化帮助我们探索数据、提出并验证假设。但无论如何,在代码层面做数据分析,就避不开被各种API的语法坑到,如果老是在基础的语法上卡壳,势必会影响了数据分析的主线和数据分析师的思路。
网络上已经有太多优秀的matplotlib的教程了,不想花太多时间出重复的教程。因此本文不是一篇正经的教程,仅作为最近读完《Matplotlib for Python Developers》后记录一些Tricks,希望能够帮matplotlib入门的玩家们少踩一些坑。
如果是出于数据分析结束后出报告的目的,不是很推荐初学者直接从matplotlib底层肝。高级的API有Seaborn、Bokeh,还有很多优秀的可视化工具:
- Excel:Excel就非常适合新手出图了,玩的溜Excel也可以花式
- Tableau、PowerBI:近年来BI软件也非常流行,用于发布交互式图表
- JMP:SaS旗下一款轻量的数据分析平台,交互式EDA体验非常棒
- EChart:百度基于JS开发的可视化库,可以嵌入到Web、PPT、app,还支持调用Python接口
以及matplotlib,用好的也是个大杀器;上得厅堂下得厨房 :>
Hold功能
matplotlib在画完一个图形后可以接着在axes上画下一个图形,是因为hold属性默认是enabled的,你可以认为它声明了保留当前figure上所有画过的图形,而不是每调用一次plot就覆盖上一次的。
plt.hold(False) # 关闭hold功能
plt.plot([1,2,3])
plt.plot([2,4,6]) # hold关上后,每一次plot会覆盖之前的绘图
Grid
grid()函数接收 Boolean型的参数:
- True表示打开网格
- False表示关闭网格
处理坐标轴axes
matplotlib会自动地设置坐标轴范围,以完整得包含所有的数据点
plt.axis()
不带任何参数,返回 当前坐标轴的范围:[x_min, x_max, y_min, y_max]
我们可以通过相同的格式,来重新设置范围:plt.axis([x_min, x_max, y_min, y_max])
也可以通过关键字,仅设置某一个边界:plt.axis(xmin=xxx, y_max=xxx)
mpl提供了另外一组函数,单独控制某一根轴:xlim()、ylim()
同样,不带参数的话返回当前范围
添加Legend
方法一:绘制每一条曲线时,指定label参数 用来给曲线命名。这样直接不带参数调用plt.legend(),就可以显示图例了
方法二:直接 传一个 字符串列表给 legend(),该方法有个缺点:我们必须记住之前所有plot的顺序,因为legend通过顺序来匹配label
loc参数:best、center、right、upper left、center left、lower center、lower right、
还可以通过 一个坐标tuple来指定:
(0,1) 代表 左上
(0.5,0.5) 代表 中间
甚至可以放到绘图区域的外面 loc=(-0.1,0.9)
ncol参数:图例占几行
Saving to file
plt.savefig('plot123.png') 保存图片的格式是根据 后缀名来判断的
两个参数共同决定图片的像素大小:
- figure size mpl.rcParams['figure.figsize']
- dpi mpl.rcParams['savefig.dpi']
例如 8x6 inches figure,100dpi的图片,最终像素是 800x600
当图片显示在屏幕上时,长度单位是被忽略的,单纯显示像素
当打印或在文档中使用时,size和dpi决定了 怎么缩放图片
图片的size使用inch来表示,但所有其他属性都被表示为 像素点 例如line width、font size
可以直接在savefig时,通过指定dpi
参数
如果需要只保存图片进文件,不进行任何显示
import matplotlib as mpl
mpl.use('Agg') # 一定要放在import pyplot之前
import matplotlib.pyplot as plt
transparent参数:使背景透明。例如准备放到网页上,如果网页本身有自己的背景颜色,那么透明背景就很有用
savefig()另一个强大的功能,就是支持接收一个 打开的file对象。这在开发Web服务器时很有用,因为我们可以通过网络输出streaming
装饰图表:Styles、Types
Markers & line styles
默认设置下,Matplotlib使用单个点 表示 Markers;使用 细直线段 表示 Lines
plot()有三个方面的定制化:
- 颜色
- 线型
- 标记样式
当三个参数都需要指定时,按照以下顺序: colors,lines,markers 例如'cx--'
颜色:plt.plot(y,'m')
有多种方式指定颜色:
- Full color name:例如'yellow'
- 十六进制字符串:例如 '#FF00FF'
- RGB或RGBA tuples:例如 (1,0,1,1)
- 灰度值(字符串形式):例如 '0.7'
使用关键字参数来精确控制单项:
- color 或 c
- linestyle
- linewidth
- marker
- markeredgecolor
- markeredgewidth
- markerfacecolor
- markersize
处理X、Y轴
ticks
指坐标轴上的小线段,往往与 axes labels 成对出现
不带参数时,plt.xticks() 返回当前的 ticks位置 与 对应的labels
locs, labels = plt.xticks()
同理,我们也可以传入参数:
- Locations of the ticks
- Labels to draw at these locations (if necessary)
注解:Text、annotations
text()
xlabel()、ylabel()、title()这些函数都是在figure周围写文字,
而在figure内部写文字要使用plt.text(x, y, text)
x,y以data坐标系指定了文字的位置,可以简单理解为在图上画一个数据点 那么这还与坐标轴范围也有关
如果想要在相对于figure的某个固定位置写字,那么推荐使用figure.text()
(0,0)表示左下角
(1,1)表示右上角
annotate()
annotate()函数时需要考虑2个坐标点:
- graph point:想要指向的点
- plot point:放说明文字的点
以上两个,都以data坐标系描述
从功能上来说,text()和annotate()的本质区别是annotate可以有箭头
arrowprops = dict(facecolor='black',
shrink=0.05)
shrink:是箭头空出一些间隙,如果不设shrink那么箭头会完全连接xy和xytext两个点 0.05表示5%
frac:是箭头的头部 占总体长度的比例
headwidth:箭头宽度
添加箭头后,一般需要 手动调用ylim()和xlim() 重新调整坐标轴范围
arrow():单独画箭头
在其他图表中单独画箭头,使用arrow()函数
plt.arrow(x, y, dx, dy)
箭头从x,y开始,指向(x+dx, y+dy)
然而这个函数很难用,推荐直接使用annotate() 文本设为空字符即可
高级作图
面向对象方式
fig = plt.figure()
ax = fig.add_subplot(111)
line, = plt.plot(x,y)
title = ax.set_title('This is title')
plt.show()
plot()之类的函数返回 Line2D 的list,由于我们只用plot画了一条曲线,因此list中只有一个元素
使用逗号,就能够直接将第一个元素 赋给 line
plt.figure只返回figure对象,用来添加Axes
fig.add_subplot() 用来在fig上添加Axes,并返回Axes对象
从high level到lower level:
- FigureCanvas:Container for the Figure instance
- Figure:Container for one or more Axes instances
- Axes:rectangular areas to hold the basic elements, such as lines,text
双Y轴 或 双X轴
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax1.plot(x,y1)
ax2 = ax1.twinx()
ax1.plot(x,y2)
plt.show()
事实上,两个不同的Axes实例被创建,就像一个被放在了另一个上方一样
twinx()函数的trick:创建另一个axes,把ax2放到与ax1完全相同的位置
twiny()类似,让两个X轴共享Y轴
对数轴刻度
ax.set_xscale('log')
ax.set_ysacle('log')
几个高级的API:
- ax.semilogx(x, y) 直接像调用plot一样即可,自带了ax.set_xscale('log')
- ax.loglog(x,y) 对两个周都进行了取对数
默认的底数是10,log_10 basex和basey参数可以指定别的
共享坐标轴
使用twinx可以在一张fig里共享坐标轴
如果是在多个fig之间共享坐标轴呢?
ax1 = fig.add_subplot(311)
ax2 = fig.add_subplot(312, sharex=ax1)
ax3 = fig.add_subplot(313, sharex=ax1)
日期坐标
plt.plot_date() 是matplotlib专门用来画日期坐标轴的函数
plt.plot_date(date, values, linestyle='-')
如果不指定linestyle,那么默认画的是散点图
date数据,必须用date2num()函数转换
因为matplotlib使用浮点数表示从0001-01-01UTC起的日期
日期格式
实用函数:
- date2num()
- num2date()
- drange(): 直接生成matplotlib用浮点数表示的日期格式
格式化axes ticks:locators & formatters
画日期坐标,最让新手头疼和困惑的应该就是怎么调ticks了。
- Locators:控制ticks的位置
- Formatters:控制 label的格式
两个类都有major
和minor
模式:major是默认激活的,就是通常我们看到的;minor就是我们常说的副刻度线 默认被赋值了NullLocator和NullFormatter
常用的Locator有:MinuteLocator, HourLocator, DayLocator, WeekdayLocator, MonthLocator, YearLocator
举例来说,DayLocator默认每个一天画一条刻度,还可以通过设置参数 每几天画一条刻度线
ax.plot_date(dates, y, linestyle='-');
dateFmt = mpl.dates.DateFormatter('%Y-%m-%d')
ax.xaxis.set_major_formatter(dateFmt)
daysLoc = mpl.dates.DayLocator()
hoursLoc = mpl.dates.HourLocator(interval=6)
ax.xaxis.set_major_locator(daysLoc)
ax.xaxis.set_minor_locator(hoursLoc)
自定义formatters:
import matplotlib.ticker as ticker
def format_func(x, pos):
return <a transformation on x>
formatter = ticker.FuncFormatter(format_func)
ax.xaxis.set_major_formatter(formatter)
像这样,我们定义的format_func 会在画每一个label时被调用一次
接收到的参数是 当前label 和 它在axis上的位置
各类图表
直方图:plt.hist(y, bin)
误差线:plt.errorbar(x, y, yerr, fmt='.-')
条形图:plt.bar(x,y, bottom,width, color, xerr, yerr, )
饼图: plt.pie(x, labels, explode, autopct='formatting string')
散点图:plt.scatter(x,y)
雷达图:plt.polar(theta, r)
等高线图:plt.contour()
图片
imread():读取图片文件并转换为Numpy array
imshow():使用array显示图片
在处理图片时,默认的坐标原点在左上角 origin='upper'
可以通过修改origin
关键字,例如 origin='lower' 这样就符合我们理解的坐标系