摘要这一篇文章会介绍一下python数据分析中matplotlib的使用。把一些常用的方法记录在此,方便自己以后的查阅与学习。
Matploylib介绍
在数据分析的时候,我们经常需要将数据可视化,这是就需要使用matplotlib模块了。
我们首先将matplotlib.pyplot导入后命名为plt, 在后面的内容中,出现的plt都默认是matplotlib.pyplot包
import matplotlib.pyplot as plt
%matplotlib inline
在使用jupyter的时候需要加上后面这句.
可视化的一些 Tips
当数据相差比较大的时候,绘制图像的时候有一部分数据挤在一起,这个时候可以使用 Log 对数据先进行对数处理,接着在进行绘图;
当坐标轴的数字比较大的时候,可以将其除一个数,使其变小,在 label 上进说明即可;
matplotlib基础
matplotlib是面向对象的绘图工具包,绘制的图形中每一个元素都是一个对象,比如线条,文字,刻度等信息,可以通过修改这些对象的属性,从而改变绘图样式。
matplotlib中主要的绘图对象列表如下:
Figure对象,可以想象为一张画布;
Axes对象,字面理解为坐标轴(因为每一个 Axes 都有一套 X Y轴坐标系,绘制图形时基于此坐标系绘制。) 也可以认为是子图,在一个Figure对象中可以包含多个Axes对象,也就是说一张画布可以包含多个子图;
Line2D对象,代表线条;
Text对象,代表了文字,比如一张子图需要标题,就可以使用一个Text对象;
下面我们先来看一个简单的例子:
N = 50
x = np.random.random(N) # 横坐标
y = np.random.random(N) # 纵坐标
colors = np.random.random(N) # 每个坐标的颜色
area = np.pi*(10*np.random.random(N))**2 # 每个坐标的颜色
plt.scatter(x,y,s=area,c=colors,alpha=0.5)
plt.show()
我们可以看一下画出来的图像,是一个散点图
在上面这个例子中,我们没有创建任何Figure对象,这是因为plt会默认创建Figure对象并保存在plt内部。
下面我们通过plt.figure()创建一个新的Figure对象,然后在此Figure对象上创建Axies对象。
fig = plt.figure()
ax1 = fig.add_subplot(2,2,1) #添加一个Axes对象到布局为两行两列的第一个位置
ax2 = fig.add_subplot(2,2,2)
ax3 = fig.add_subplot(2,2,3)
ax1.plot(np.random.randn(50).cumsum(), 'k--')
ax2.hist(np.random.randn(100), bins=20, color='k')
ax3.scatter(np.arange(30), np.arange(30) + 3 * np.random.randn(30))
fig.show()
我们首先创建一个Figure对象,接着插入三个Axes对象,接着在Axes对象上绘制累积和线图,直方图以及散点图。
我们要注意的是上面的fig.add_subplot(2,2,1)表示添加一个Axes对象到布局为两行两列的第一个位置。
我们看一下上面代码绘制出图像的样子:
到这里我们就把matplotlib的基本功能看完了,下面我们看一下常用的属性设置。
子图的绘制
这里我们详细说明一下子图的绘制. matplotlib使用plt.subplots来绘制子图, 我们可以使用下面的命令绘制一个2行, 5列的子图.
fig, axs = plt.subplots(2, 5, figsize=(15, 6), facecolor='w', edgecolor='k')
fig.subplots_adjust(hspace = .5, wspace=.001)
axs = axs.ravel()
for i in range(10):
axs[i].contourf(np.random.rand(10,10),5,cmap=plt.cm.Oranges)
axs[i].set_title(str(250+i))
子图共享坐标轴
有下面两种方式可以共享子图的坐标轴, 我们可以设置为全局共享, 及所有的子图都能共享坐标轴:
fig, (ax1, ax2) = plt.subplots(nrows=2, sharex=True)
我们也可以为某一个单独的子图设置共享:
fig=plt.figure()
ax1 = plt.subplot(211)
ax2 = plt.subplot(212, sharex = ax1)
下面看一个简单的例子, 下面的setp表示Set a property, 是用来设置坐标轴的属性的:
import matplotlib.pyplot as plt
import numpy as np
t = np.arange(0.01, 5.0, 0.01)
s1 = np.sin(2 * np.pi * t)
s2 = np.exp(-t)
s3 = np.sin(4 * np.pi * t)
ax1 = plt.subplot(311)
plt.plot(t, s1)
plt.setp(ax1.get_xticklabels(), fontsize=6)
# share x only
ax2 = plt.subplot(312, sharex=ax1)
plt.plot(t, s2)
# make these tick labels invisible
plt.setp(ax2.get_xticklabels(), visible=False)
# share x and y
ax3 = plt.subplot(313, sharex=ax1, sharey=ax1)
plt.plot(t, s3)
plt.xlim(0.01, 5.0)
plt.show()
常用属性设置
matplotlib绘制的图形可以设置各种属性,比如设置坐标系的刻度,标题,标签等属性。 matplotplib绘制图形时,基于X, Y轴坐标系绘图。我们可以设置X, Y坐标的各种属性,比如刻度,范围,标签等属性。
matplotlib显示中文
我们在开头加上下面的代码即可正常显示中文.
from pylab import * # 设置显示中文
mpl.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
关于这里字体名称的设置,我们可以通过下面的方式来进行查看:
import matplotlib
a=sorted([f.name for f in matplotlib.font_manager.fontManager.ttflist])
for i in a:
print(i)
这里会打印出所有的注册的字体的名称,大致如下所示:
可以使用「FZShuTi」表示方正舒体。
数字与颜色的转换-map number to color
import matplotlib.cm as cm
print(cm.hot(0.3))
也可以使用下面的样式进行绘制:
cmap = plt.get_cmap('rainbow', 12)
设置标题,坐标刻度
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
# 设置标题
ax.set_title('Test Title')
major_ticks = np.arange(0, 101, 20)
minor_ticks = np.arange(0, 101, 5)
# 设置刻度
ax.set_xticks(major_ticks)
ax.set_xticks(minor_ticks, minor=True) # 这个是短线
ax.set_yticks(major_ticks)
ax.set_yticks(minor_ticks, minor=True)
# 设置 X, Y 轴 标签
ax.set_xlabel("X axis")
ax.set_ylabel("Y axis")
# 设置网格
ax.grid(which='minor', alpha=0.2)
ax.grid(which='major', alpha=0.5)
# 添加文字
ax.text(42.5, 50, "Hello World")
fig.show()
可以看到下面的效果
设置标题位置
直接使用 set_title 会默认将标题生成在图像的上部。但是有的时候我们需要自动调整 title 的位置。我们可以通过设置 set_title 中的参数 y 来改变 title 的位置。下面看一个简单的例子,显示默认生成的标题的位置:
fig, ax = plt.subplots(figsize=(6, 3), subplot_kw=dict(aspect="equal"))
ax.set_title("Title Position")
生成的结果如下所示:
上面是默认生成的标题的位置,我们可以通过控制 y 来修改标题的位置。如下所示:
fig, ax = plt.subplots(figsize=(6, 3), subplot_kw=dict(aspect="equal"))
ax.set_title("Title Position", y=1.5)
这个时候看生成的效果,可以看到他的标题的位置就在图像的上方一些:
加入文字
对于文字, 我们可以再外面加上边框等. 上面是在文字周围加上边框, 底色是红色.
text(x, y, s, bbox=dict(facecolor='red', alpha=0.5))
例如下面是对MNIST降维的结果
ax.text(np.mean(v_x[ix][:,0]), np.mean(v_x[ix][:,1]), key, fontsize=18, bbox=dict(facecolor='white', alpha=0.5))
关于这张图片的详细生成过程, 可以参考链接, t-SNE与AE对MNIST可视化
设置坐标轴刻度与坐标轴名称
注意, 在图中有两个部分, 我把他叫做坐标轴刻度与刻度名称, 坐标轴本身的名称. 我们通过下面一个小例子来看一下是如何来进行设置他们的.
from pylab import * # 设置显示中文
mpl.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
x = np.linspace(0, 1, 100)
fig = plt.figure(figsize=(12,8))
ax = fig.add_subplot(1,1,1)
ax.set_title(u'设置曲线颜色与图例', fontsize=17)
# 绘制图形
ax.plot(x, x ** 2, 'b.', label=r'$y = x^{2}$')
# 设置坐标轴的标签
ax.yaxis.set_tick_params(labelsize=15) # 设置y轴的字体的大小
ax.set_xticks(np.linspace(0, 1, 11)) # 设置xticks出现的位置
xticks = [i if i in [0, 0.5, 0.8, 1.0] else '' for i in np.linspace(0, 1, 11)] # 只显示特定数字
ax.set_xticklabels(xticks, rotation=-45, fontsize=17) # 设置xticks的值
# 设置坐标轴名称
ax.set_ylabel("这是Y轴", fontsize='xx-large')
ax.set_xlabel('这是X轴', fontsize='xx-large')
# 自动生成图例
ax.legend(fontsize=17)
# 设置图像x,y轴的范围,都是从0-1
ax.axis([0, 1, 0, 1])
fig.show()
这上面的内容包括:
设置坐标轴刻度的间隔
设置坐标轴刻度的名称, 调整大小和倾斜角度
设置x轴, y轴的名称
设置坐标轴为log scale
有的时候, 我们需要设置坐标轴为log scale, 我们可以使用plt.yscale进行设置, 可以参考下面的代码.
dt = 0.01
x = np.arange(-50.0, 50.0, dt)
y = np.arange(0, 100.0, dt)
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.plot(x, y)
# 设置y scale
plt.yscale('log')
plt.ylabel('logy') # 设置y轴的label
最后绘制出来的结果如下图所示, 看y轴的刻度, 可以看到此时是log scale了:
设置曲线颜色,图例
# 设置显示中文
from pylab import *
mpl.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
x = np.linspace(0, 1,100)
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.set_title(u'设置曲线颜色与图例')
# 四个参数分别表示x,y轴数据,'b--'表示颜色是蓝色样式是虚线,最后一个表示标签,支持LaTex
ax.plot(x, x ** (1/8), 'b--', label=r'$y = x^{1/8}$')
ax.plot(x, x ** 8, 'r--', label=r'$y = x^{8}$')
ax.plot(x, x ** (1/2), 'r.', label=r'$y = x^{1/2}$')
ax.plot(x, x ** 2, 'b.', label=r'$y = x^{2}$')
ax.plot(x, x, 'g-', label=r'$y = x$')
# 自动生成图例
ax.legend()
# 设置图像x,y轴的范围,都是从0-1
ax.axis([0, 1, 0, 1])
fig.show()
上面的代码运行完毕后我们可以看到如下的图像
关于一些常用的样式,我们记录一下:
线的样式linestyle=有
'-' 默认实线
'--' 虚线
'-.' 间断线
':' 点状线
图例与pandas结合使用
有的时候, 我们的使用pandas的数据来进行绘图的时候, 图例是dataframe中某一列的数据, 这个时候我们就可以使用下面的方式插入图例.
plt.legend(legend.values,loc=4)
关于图例位置自定义
要是我们想要自定义图例的位置, 比如说希望图例出现在曲线的上面, 或者周围, 我们可以使用ax.text来进行实现. 我们看一下下面的这个例子.
from pylab import * # 设置显示中文
mpl.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
x = np.linspace(0, 1,100)
fig = plt.figure(figsize=(12,8))
ax = fig.add_subplot(1,1,1)
ax.set_title(u'设置曲线颜色与图例')
# 四个参数分别表示x,y轴数据,'b--'表示颜色是蓝色样式是虚线,最后一个表示标签,支持LaTex
ax.plot(x, x ** 8, 'r--', label=r'$y = x^{8}$')
ax.plot(x, x ** 2, 'b.', label=r'$y = x^{2}$')
# 手动设置图例
ax.text(x[-10], 0.9*(x ** 8) [-10], r'$y = x^{8}$', fontsize=17)
ax.text(x[-26], 1.2*(x ** 2) [-26], r'$y = x^{2}$', fontsize=17)
# 自动生成图例
ax.legend()
# 设置图像x,y轴的范围,都是从0-1
ax.axis([0, 1, 0, 1])
fig.show()
最终的实现的效果如下图所示, 可以看到在两条曲线周围都有了图例:
绘制图像的样式
绘制xkcd样式图片
我们可以绘制漫画风格的图片,只需要在初始设定plt.xkcd()即可;
plt.xkcd()
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
np.random.seed(7)
x = np.linspace(1, 10, 50)
y = 2*x + 0.5*x**2 + 0.3*x**4 - 0.025*x**5 + 5*np.random.rand(50)
ax.scatter(x, y)
最终的绘制效果如下图所示:
我们需要注意的是, 在设置xkcd样式的时候, 可以这样写, 这样可以保证只有当前的图像应用这个风格.
with plt.xkcd():
# This figure will be in XKCD-style
fig1 = plt.figure()
# ...
# This figure will be in regular style
fig2 = plt.figure()
关于 xkcd 样式中文的设置,需要在定义风格之后进行,下面是一个例子:
plt.xkcd()
plt.rcParams['font.family'] = ['FZShuTi']
下面看一个简单的例子,包含中文的 xkcd 样式的图像:
plt.xkcd()
plt.rcParams['font.family'] = ['FZShuTi'] # 这个需要在设置样式之后再设置
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.set_title(u'是否考虑自己未来的规划', fontsize=25)
x = np.arange(3)*1.2
y = [137, 140, 176] # 有
z = [33, 45, 38] # 没有
sum = [i+j for i,j in zip(y,z)] # 计算每个年纪所占的比例
y = [i/j for i,j in zip(y,sum)]
z = [i/j for i,j in zip(z,sum)]
w=0.3
# 绘制多个bar在同一个图中, 这里需要控制width
plt.bar(x-w/2, y, width=w, align='center', label='有')
plt.bar(x+w/2, z, width=w, align='center', label='没有')
ax.set_xticks(x) # 设置xticks出现的位置
ax.set_xticklabels(['高一', '高二', '高三'], rotation='30', fontsize='xx-large')
ax.plot(x, y, c='green') # 画出曲线
ax.legend(bbox_to_anchor=(1, 0.95)) # 绘制图例
plt.show()
最终的输出格式如下所示:
图像的样式概览
除了上面的风格之外, 我们还有不同类型的风格可以进行设置. 例如下面是设置为默认的风格, 完整的风格间下面的参考链接.
# 设置画图的style
matplotlib.style.use('default')
绘制其他样式
对于绘制其他样式的图片,只需要修改plt.style.use即可,可以看下面的简单的例子
# 生成随机数据
np.random.seed(7)
x = np.linspace(1, 12, 10)
y = 2*x + 0.7*x**2 - 20*np.sin(x) - 20*np.cos(x) + 5*np.random.rand(10)
plt.style.use("ggplot") # 使用美观的样式
plt.scatter(x, y)
设置图像颜色风格
除了上面设置图像的风格之外,我们还可以设置图像的颜色的风格。我们可以使用下面的命令来设置颜色的样式。
plt.set_cmap('RdBu')
我们来看一下最终的效果,使用柱状图来举一个例子。
x = np.arange(3)*1.2
y = [4, 9, 2]
z = [1, 2, 3]
k = [11, 12, 13]
ax = plt.subplot(111)
plt.set_cmap('RdBu')
w=0.3
# 绘制多个bar在同一个图中, 这里需要控制width
plt.bar(x-w, y, width=w, align='center')
plt.bar(x, z, width=w, align='center')
plt.bar(x+w, k, width=w, align='center')
ax.set_xticks(x) # 设置xticks出现的位置
ax.set_xticklabels(['1','2','3'], rotation='vertical', fontsize = 'xx-large')
ax.autoscale(tight=True)
plt.show()
这是一个绘制多个柱状图的方式,最终的效果如下所示。
设置图像颜色
除了上面使用指定的颜色,我们还可以指定我们需要的颜色,还是使用上面的柱状图作为例子我们简单来看一下。
其实基本是一样的,只是在绘图的时候指定了颜色,color=.
这三种颜色搭配我感觉还是不错的,在这里放一下(最终的效果见下面)。
#e0109c
#1b71f1
#9eed3b
x = np.arange(3)*1.2
y = [4, 9, 2]
z = [1, 2, 3]
k = [11, 12, 13]
ax = plt.subplot(111)
w=0.3
# 绘制多个bar在同一个图中, 这里需要控制width
plt.bar(x-w, y, width=w, color='#e0109c', align='center')
plt.bar(x, z, width=w, color='#1b71f1', align='center')
plt.bar(x+w, k, width=w, color='#9eed3b', align='center')
ax.set_xticks(x) # 设置xticks出现的位置
ax.set_xticklabels(['1','2','3'], rotation='vertical', fontsize = 'xx-large')
ax.autoscale(tight=True)
plt.show()
上面的颜色,绘制出来的效果如下所示。
常用图像
我们在数据分析的时候,经常会用到各种各样的图像,我们就在这里总结一下。
线形图
这个就有点类似把一些散点连起来,我们使用Axes.plot进行绘制
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
x = np.arange(10)
y = x**2
ax.plot(x,y)
fig.show()
柱状图
纵向的柱状图
fig = plt.figure(figsize=(7,5))
ax = fig.add_subplot(1,1,1)
bar_data = [5, 20, 15, 25, 10]
bar_labels = ['Tom', 'Dick', 'Harry', 'Slim', 'Jim']
plt.bar(range(len(bar_data)), bar_data, tick_label=bar_labels)
plt.show()
堆叠柱状图
我们可以将两个柱状图以堆叠的形式画在一起。下面看一个简单的例子。
data = pd.DataFrame({'A': [1,3,2,4], 'B': [4,2,3,1], 'index': ['test1', 'test2', 'test3', 'test4']})
创建的数据样例如下所示:
我们希望画两个柱状图,第一个柱状图的高度就是上面表格中的A,第二个柱状图从A的位置开始画起,他的高度是B,这样就是两个柱状图堆叠在一起的效果。
plt.rcParams['figure.figsize'] = (10, 6)
plt.bar(x='index', height='A', data=data, width=1.0, label='下')
plt.bar(x='index', height='B', bottom='A', data=data, width=1, label='上')
ax = plt.gca()
ax.legend(prop=myfont, bbox_to_anchor=(1.0, 0.9))
最终的效果如下所示:
横向柱状图
将上面的plt.bar替换为plt.barh可以画出横向的柱状图. 一般用在labels比较长,或是比较多的时候,比如说我们可以绘制出下面的图像.
参考链接 : matplotlib绘图——柱状图
绘制多条柱状图
有的时候,我们需要绘制多条柱状图在一起,从而来进行比较,可以使用下面的方式进行绘制.(其实这一部分的内容是和上面介绍设置图像颜色, 图像风格是重复的, 在这里再简单说明一下)
x = np.arange(3)*1.2
y = [4, 9, 2]
z = [1, 2, 3]
k = [11, 12, 13]
ax = plt.subplot(111)
w=0.3
# 绘制多个bar在同一个图中, 这里需要控制width
plt.bar(x-w, y, width=w, color='#e0109c', align='center')
plt.bar(x, z, width=w, color='#1b71f1', align='center')
plt.bar(x+w, k, width=w, color='#9eed3b', align='center')
ax.set_xticks(x) # 设置xticks出现的位置
ax.set_xticklabels(['1','2','3'], rotation='vertical', fontsize = 'xx-large')
ax.autoscale(tight=True)
plt.show()
绘制的结果如下:
那么这个图什么时候可以用到呢,就是我们可以展示同一类的TP, FP, FN这些指标。如下图所示(下面是使用NSL-KDD做的实验的结果).
参考链接 : Python matplotlib multiple bars
饼图的绘制
基础饼图的绘制
我们只需要给定饼图中每一块的大小,每一块的 label,每一块是否要突出,即可绘制出一个最基础的饼图。
# Pie chart, where the slices will be ordered and plotted counter-clockwise:
labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'
sizes = [15, 30, 45, 10]
explode = (0, 0.1, 0, 0) # only "explode" the 2nd slice (i.e. 'Hogs')
fig1, ax1 = plt.subplots()
ax1.pie(sizes, explode=explode, labels=labels, autopct='%1.1f%%',
shadow=True, startangle=90)
ax1.axis('equal') # Equal aspect ratio ensures that pie is drawn as a circle.
plt.show()
绘制的效果最终如下所示:
对饼图进行 Label
下面代码只需要修改 data,title,和 recipe 即可,后面的都可以不进行修改。
fig, ax = plt.subplots(figsize=(7, 5), subplot_kw=dict(aspect="equal"))
y1 = [135, 148, 166]
y3 = [73, 95, 93]
y4 = [85, 99, 82]
y5 = [114, 121, 122]
y6 = [105, 107, 100]
data = [np.sum(i) for i in [y1, y2, y3, y4, y5, y6]]
title = ["开设职业生涯规划课程",
"举办职业规划讲座",
"在学校开通职业规划评价系统",
"在学校设立专门的职业指导中心",
"创建丰富多彩的职业体验课程",
"加强教师和家长的指导"]
recipe = ['{} {:<3.2f} %'.format(i,j/np.sum(data)*100) for i,j in zip(title, data)] # 设置标题
# 下面的不需要修改
wedges, texts = ax.pie(data, wedgeprops=dict(width=0.4), startangle=-40)
bbox_props = dict(boxstyle="square,pad=0.3", fc="w", ec="k", lw=0.72)
kw = dict(arrowprops=dict(arrowstyle="-"),
bbox=bbox_props, zorder=0, va="center")
for i, p in enumerate(wedges):
ang = (p.theta2 - p.theta1)/2. + p.theta1
y = np.sin(np.deg2rad(ang))
x = np.cos(np.deg2rad(ang))
horizontalalignment = {-1: "right", 1: "left"}[int(np.sign(x))]
connectionstyle = "angle,angleA=0,angleB={}".format(ang)
kw["arrowprops"].update({"connectionstyle": connectionstyle})
ax.annotate(recipe[i], xy=(x, y), xytext=(1.35*np.sign(x), 1.4*y),
horizontalalignment=horizontalalignment, **kw)
ax.set_title(u"您认为学校开展职业生涯规划教育的措施有哪些", fontsize=25, y=1.2)
plt.show()
最终生成的效果如下所示:
直方图
直方图X轴一般是统计的样本,而Y轴一般是样本对应的统计度量。
为了构建直方图,第一步是将值的范围分段,即将整个值的范围分成一系列间隔,然后计算每个间隔中有多少值。 这些值通常被指定为连续的,不重叠的变量间隔。 间隔必须相邻,并且通常是(但不是必须的)相等的大小。在 matplotlib 中可以使用Axes.hist方法绘制直方图。
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
data = np.random.normal(0,20,1000) # 在0-20之间产生1000个随机数
bins = np.arange(-100,100,5) # 产生区间刻度
ax.hist(data,bins=bins)
fig.show()
散点图
散点图,将所有的数据值在图形中绘制成点,这样有多少数据值在图形中就会有多少个点。通过这些数据点可以看出数据值的分布模式,比如是否有聚类模式,或者相关关系或者发现离群点。在 matplotlib 中可以通过Axes.scatter绘制散点图。
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
x = np.arange(1,100,1)
y = x**2+100*x*np.random.random(len(x))
ax.scatter(x,y)
fig.show()
散点图的美化
一些比较规整的,类似于表格的数据,也是可以使用散点图进行绘制。我们首先生成样例数据,这里是生成每一年,每一个年龄段的人口的数据。也就是1年,如果年龄段是0-80,也就是一年会有80组数据。
data = []
years = [str(i) for i in list(range(1990, 2020, 1))] # 所有的年份
ages = [str(i) for i in list(range(0, 81, 5))] # 所有的年龄段
populations = [10000*i for i in list(range(0, 81, 5))] # 每个年龄段的人口
for year_index, year in enumerate(years):
for age_index, age in enumerate(ages):
data.append([year, age, (1+0.1*year_index)*populations[age_index]])
plot_data = pd.DataFrame(data, columns=['year', 'age', 'population'])
plot_data.head()
生成的数据如下所示:
我们使用散点图对上面的数据进行可视化:
plt.rcParams['figure.figsize'] = (18, 8)
plt.scatter(
x=plot_data['year'],
y=plot_data['age'],
c=plot_data['population'],
s=plot_data['population']*0.0005,
ec='tab:gray',
cmap=plt.cm.RdBu_r,
alpha=0.8)
ax = plt.gca()
# 坐标轴控制
ax.set_xticks([years[i] for i in range(0, len(years), int(len(years)/5))])
ax.set_yticks([ages[i] for i in range(0, len(ages), int(len(ages)/5))])
# 不显示左侧和底部纵坐标轴
ax.spines['left'].set_visible(False)
ax.spines['bottom'].set_visible(False)
# 显示 y 轴网格线
ax.grid(b=False, axis='y', lw=1)
plt.ylabel('Mean Age')
最终的效果如下所示:
高阶散点图-指定不同类别使用不同颜色
如果散点图中有不同的类别, 同时希望可以对不同类别使用不同的颜色, 并使用图例标注出来, 我们需要依序进行绘制.
以下是一个完整的例子, 详细说明可以查看链接: matplotlib绘图优化-散点图绘制图例
cmap = plt.get_cmap('rainbow', 12) # 数字与颜色的转换
scatter_x = np.array([1,2,3,4,5])
scatter_y = np.array([5,4,3,2,1])
group = np.array([1,3,2,1,3])
cdict = {1: '111', 2: '222', 3: '333'}
fig, ax = plt.subplots()
for key in cdict.keys():
ix = np.where(group == key)
ax.scatter(scatter_x[ix], scatter_y[ix], color = cmap(key), label = key, s = 100) # 注意这里color的指定
ax.legend()
plt.show()
最终的结果如下所示:
除了可以控制颜色的不同以外, 我们还可以控制形状的不同, 可以通过简单设置marker来达到效果, 下面有12种不同的marker:
markers = ["8","s","p","P","*","h","H","+","x","X","D","d"]
绘制多边形(区间的绘制)
我们可以使用plt.fill进行多边形的绘制,我们先看一个简单的例子:
# 绘制一个多边形的区域
test_x = np.array([1,2,3])
test_y = np.array([4,1,2])
fig, axes = plt.subplots(nrows=1, ncols=1,figsize=(13,7))
axes.fill(test_x,test_y)
我们可以使用这个方法来绘制一个区间的效果;
# 绘制一个多边形的区域
test_x = np.linspace(0.1, 9.9, 200)
test_y = np.sin(test_x)
fig, axes = plt.subplots(nrows=1, ncols=1,figsize=(13,7))
axes.plot(test_x,test_y,c='r')
axes.fill(np.concatenate([test_x,test_x[::-1]]),np.concatenate([test_y + 1, test_y - 1]))
箱线图
箱线图可以看出数据的分散程度,异常值等信息,箱线图根据一组数据的以下 5 个统计值进行绘制:
最小值;
第1四分位数;
中位数;
第3四分位数;
最大值;
在 matplotlib 中可以使用Axes.boxplot方法绘制箱线图
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
# 产生 50 个小于 100 的随机数
spread = np.random.rand(50) * 100
# 产生 25 个值为 50 的数据
center = np.ones(25) * 50
# 异常值
outlier_high = np.random.rand(10) * 100 + 100
outlier_low = np.random.rand(10) * -100
data = np.concatenate((spread, center, outlier_high, outlier_low), 0)
ax.boxplot(data)
fig.show()
上面的代码中,我们特意创建了 data 数据,可以推断出该数据的中位数是 50,还有一些其他异常值,绘制的图形如下:
绘制动态图
除了能绘制上面的静态图像,我们还可以绘制动态图像,下面我们来举一个小例子来说明matplotlib如何绘制动态图像。
动态图主要是通过animation模块实现。具体就是matplotlib.animation.FuncAnimation(fig, func)。其中fig代表所绘制的图像。而func可以看作是更新函数,它刷新每一帧的值。
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
x = np.arange(0,2*np.pi,0.01)
line, = plt.plot(x,np.sin(x))
# 更新函数
def update(i):
line.set_ydata(np.sin(x+i/10))
return line
animation = animation.FuncAnimation(fig,update,interval=20)
plt.show()
上面的interval表示更新频率,以ms计。(说实话,制作动画还是喜欢使用Mathematica来进行制作)
看一下上面的绘制出的效果
绘制三维图像
最后,我们来说一下三维图像的绘制。
绘制三维散点图
import numpy as np
# 导入2d,3d的绘图模块
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
# x, y, z 均为 0 到 1 之间的 100 个随机数
x = np.random.normal(0, 1, 100)
y = np.random.normal(0, 1, 100)
z = np.random.normal(0, 1, 100)
fig = plt.figure()
ax = Axes3D(fig)
ax.scatter(x,y,z)
plt.show()
绘制三维线形图
# 载入模块
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
# 生成数据
x = np.linspace(-6 * np.pi, 6 * np.pi, 1000)
y = np.sin(x)
z = np.cos(x)
# 创建 3D 图形对象
fig = plt.figure()
ax = Axes3D(fig)
# 绘制线型图
ax.plot(x, y, z)
# 显示图
plt.show()
绘制三维曲面图
# 载入模块
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# 创建 3D 图形对象
fig = plt.figure()
ax = Axes3D(fig)
# 生成数据
X = np.arange(-2, 2, 0.1)
Y = np.arange(-2, 2, 0.1)
X, Y = np.meshgrid(X, Y) #注意这一步
Z = np.sqrt(X ** 2 + Y ** 2)
# 绘制曲面图,并使用 cmap 着色
ax.plot_surface(X, Y, Z, cmap=plt.cm.winter)
plt.show()
这个上面的meshgrid是用来生成底部的网格的,我们可以看一下x,y是什么
运行上面的代码,于是我们可以得到下面的图像
子图的绘制
之前绘制二维图像的时候我们是通过.add_subplot()来绘制子图的,其实在三维的时候也是一样的,只是注意 3D 绘图时要添加 projection='3d' 参数,下面我们看一个具体的例子。
# -*- coding: utf-8 -*
# 载入模块
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
# 创建 1 张画布
fig = plt.figure()
#===============
# 向画布添加子图 1
ax1 = fig.add_subplot(1, 2, 1, projection='3d')
# 生成子图 1 数据
x = np.linspace(-6 * np.pi, 6 * np.pi, 1000)
y = np.sin(x)
z = np.cos(x)
# 绘制第 1 张图
ax1.plot(x, y, z)
#===============
# 向画布添加子图 2
ax2 = fig.add_subplot(1, 2, 2, projection='3d')
# 生成子图 2 数据
X = np.arange(-2, 2, 0.1)
Y = np.arange(-2, 2, 0.1)
X, Y = np.meshgrid(X, Y)
Z = np.sqrt(X ** 2 + Y ** 2)
# 绘制第 2 张图
ax2.plot_surface(X, Y, Z, cmap=plt.cm.winter)
# 显示图
plt.show()
上面就是matplotlib的一些常用的用法了,记录在此也方便自己的查阅。