绘制函数图
前面我们介绍的都是如何使用matplotlib绘制统计图,但在数据科学领域,matplotlib也经常用来绘制函数图
1 一次函数
import numpy as np
from matplotlib import pyplot as plt
x = np.linspace(-1, 1, 50)
y = 2 * x + 1
plt.plot(x, y)
plt.show()
输出
2 同时生成多张图
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-3, 3, 50)
y1 = 2 * x + 1
y2 = x ** 2
plt.figure() #
'''在该条命令下的函数图,都在figure1中,直到下一条figure命令出现'''
plt.plot(x, y1)
plt.figure()
'''下面的内容都将在figure2窗口中'''
plt.plot(x, y2)
plt.figure(num=5, figsize=(8, 5)) #
'''给figure窗口编号为5,如果有下一个窗口的话,将会从6开始计数,
使该窗口的图幅以长宽比为8:5显示'''
plt.plot(x, y1+y2)
plt.show()
'''figure1窗口生成一条直线,
figure2窗口生成一条抛物线
figure5窗口将y1和y2复合'''
输出
Figure1
Figure2
Figure5
3 调整线条属性
import numpy as np
import matplotlib.pyplot as plt
'''调整线的颜色、宽度、线型'''
x = np.linspace(-3, 3, 50)
y1 = 2*x + 1
y2 = x**2
y3 = x**3
plt.figure(num=2)
plt.plot(x, y1)
plt.plot(x, y2, 'red', linewidth=3, linestyle='--') # 两个减号‘--’表示虚线
'''线宽默认是1'''
plt.figure()
plt.plot(x, y3)
plt.show()
输出
Figure2
Figure3
4 坐标轴设置
(1)设置坐标轴显示范围
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-3, 3, 50)
y1 = 2*x + 1
y2 = x**2
y3 = x**3
new_ticks = np.linspace(-1, 2, 5)
plt.figure()
plt.plot(x, y1, color='green')
plt.plot(x, y2)
'''虽然指定了显示范围,但是仍然可以通过图片上的十字键拖动图片'''
plt.xlim((-1, 3)) # 设置x轴的显示范围
plt.ylim((-2, 3)) # 设置y轴的显示范围
plt.show()
输出
(2)设置边缘线
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-3, 3, 50)
y1 = 2*x + 1
y2 = x**2
plt.figure()
plt.plot(x, y1, color='green')
plt.plot(x, y2)
'''获得当前图幅的边缘轴线'''
ax = plt.gca() #
'''使图幅的右边缘和上边缘消失'''
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
'''将边缘轴线移动到指定位置'''
ax.spines['bottom'].set_position(('data', 0))
ax.spines['left'].set_position(('data', 0))
'''如果设置了plt.xlim和plt.ylim,那么左边的边缘轴线必须在plt.xlim之内,
下边的边缘轴线必须在plt.ylim之内'''
'''之所以要让右边缘和上边缘消失,是因为左边缘和下边缘都有刻度,
移动的时候只能移动带刻度的边缘轴线,因此只能让右边的和上边的消失'''
'''还可以隐藏坐标轴上的值'''
plt.figure()
ax = plt.gca()
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.spines['bottom'].set_position(('data', 0))
ax.spines['left'].set_position(('data', 0))
plt.plot(x, y1, color='red')
plt.plot(x, y2)
plt.xticks(()) # 括号中间有括号表示坐标上的值不显示
plt.yticks(())
plt.show()
输出
5 在坐标轴上打点
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-3, 3, 50)
y1 = 2*x + 1
# plt.figure()
# '''scatter函数是绘制点,把(x, y1)的所有点打出来'''
# plt.scatter(x, y1) # 绘制的是一张散点图
'''在线条中取点'''
plt.figure()
ax = plt.gca()
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.spines['bottom'].set_position(('data', 0))
ax.spines['left'].set_position(('data', 0))
plt.plot(x, y1)
x0 = 1
y0 = 2*x0 + 1
plt.scatter(x0, y0) # 打点
x_k = 2
y_k = 2*x_k + 1
plt.scatter(x_k, y_k, color='r') # 绘制一个红色的点
plt.plot([x_k, x_k], [y_k, 0], 'k--', lw=1.5) # 绘制一条黑色直线,线宽为1.5
plt.show()
输出
6 标注
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-3, 3, 50)
y1 = 2*x + 1
plt.figure()
'''绘制坐标轴'''
ax = plt.gca()
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.spines['bottom'].set_position(('data', 0))
ax.spines['left'].set_position(('data', 0))
'''绘制线条'''
plt.plot(x, y1)
'''在线条中取点'''
x0 = 1
y0 = 2*x0 + 1
plt.scatter(x0, y0)
'''标注'''
plt.annotate('2x+1=%s' % y0, xy=(x0, y0), xycoords='data',
textcoords='offset points', xytext=(+30, -30), fontsize=16,
arrowprops=dict(arrowstyle='->', connectionstyle="arc3,rad=.2"))
'''显示的时候'2x0+1=y0' % y0,y0的由真实值传入,
参数xy表示注释的参考位置,
xycoords='data' 是说基于数据的值来选位置,这个所谓的数据,就是前面的参数‘xy’,
textcoords='offset points' 表示注释在图片中的起始位置是基于数据的偏移来计算的
xytext=(+30, -30) 表示“注释的左下角”相对于“数据”的具体偏移量,这里的偏移量指的是像素
fontsize=16,表示字体的大小,这里的字体大小,表示的也是像素
arrowprops是对图中箭头类型的一些设置'''
plt.text(-3.7, 3, r'$5332 This\ is\ the\ text. \mu\ \sigma_i\ \alpha_t$',
fontdict={'size': 16, 'color': 'r'})
'''-3.7, 3是注释文字左下角的位置,文字前后加$表示斜体,数字无法倾斜
文字前后加$,空格读不出来,需要空格前加斜杆,引号前面加r表示正则,
最后一个输出的是数学符号alpha
中间的一段字符串是指注释的内容,sigma_i,alpha_t这里i和t都是下标
fontdict指的是注释的设置'''
plt.show()
输出
7 绘制等高线
import numpy as np
import matplotlib.pyplot as plt
def f(x, y):
'''假设平面上的某个点的高度由该函数所确定'''
return (1 - x / 2 + x**5 + y**3) * np.exp(-x**2 -y**2)
'''假设平面被分割成了 256 x 256 的网格'''
n = 256
x = np.linspace(-3, 3, n)
y = np.linspace(-3, 3, n)
X, Y = np.meshgrid(x, y) # 生成网格
Z = f(X, Y) # 生成高度
'''给等高线填充颜色'''
plt.contourf(X, Y, Z, 8, alpha=0.75, cmap=plt.cm.hot)
''' 8 表示将高度分成10个区间,为什么8表示10个区间,我也不知奥,
只需要记住,0表示分成两个区间,m表示分成m+2个区间
alpha 表示透明度,camp表示使用的颜色映射,也就是将相应的高度转化为颜色,
这里选择plt.cm.hot作为映射'''
'''绘制等高线'''
C = plt.contour(X, Y, Z, 8, linewidth=0.5, color='black')
'''线宽是0.5,颜色是黑色'''
'''给等高线标上标签(数字)'''
plt.clabel(C, inline=True, fontsize=10)
'''inline=True表示数字在登高线里面,即在等高线上挖出一块来填写数字,
若为False,则表示等高线横穿数字,
fontsize表示字体大小'''
plt.show()
输出
8 二维图像
imshow:热图(heatmap)是数据分析的常用方法,通过色差、亮度来展示数据的差异、易于理解。Python在Matplotlib库中,调用imshow()函数实现热图绘制。
import numpy as np
import matplotlib.pyplot as plt
'''先给出一张伪图像,用一个3x3的矩阵来表示一张图像,
每一个元素表示一个像素,元素的值映射着具体的颜色'''
a = np.array([0.313660827978, 0.365348418405, 0.423733120134,
0.365348418405, 0.439599930621, 0.525083754405,
0.423733120134, 0.525083754405, 0.651536351379]).reshape(3, 3)
print(a.shape)
plt.imshow(a, interpolation='nearest', cmap='bone', origin='upper')
'''interpolation表示内插法的出图方式,cmap表示使用的颜色映射,origin表示使用什么排列方式
可以在matplotlib的官网上看到不同内插法的出图方式,详见:
http://matplotlib.org/examples/images_contours_and_fields/interpolation_methods.html
bone 是 plt.cmap.bone 的缩写
origin = 'upper'表示将数组的[0,0]索引放在轴的左上角,upper常用语矩阵或图像
若为'lower'表示将数组的[0,0]索引放在轴的左下角'''
plt.colorbar(shrink=0.9) # 添加颜色标注,shrink=0.9表示标注长度变短为原来的0.9倍
plt.show()
输出
9 三维图像
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
'''-----------------------------------------------------------------------'''
fg = plt.figure(num=1)
'''生成一张平面网格'''
x = np.arange(-4, 4, 0.25)
y = np.arange(-4, 4, 0.25)
X, Y = np.meshgrid(x, y)
'''计算网格点上的函数值'''
R = np.sqrt(X ** 2 + Y ** 2)
Z = np.sin(R)
'''在窗口中添加3D坐标轴'''
ax = Axes3D(fg) # ax即为三维图像,后面要在图像中添加信息,就是通过ax
'''绘制函数图'''
ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=plt.get_cmap('rainbow'))
''''rstride 和 cstride 用来表示网格间距,r是 row 的意思,c是 column 的意思
若为1,则表示网格线间距是0.25个坐标单位,若为2,则表示间距是0.5'''
'''绘制投影图(等高线)'''
ax.contourf(X, Y, Z, zdir='z', offset=-2, cmap=plt.get_cmap('rainbow'))
'''zdir='z' 和 offset=-2,表示等高线投影到 z=-2 所在平面'''
'''之前等高线的那一节,用的函数是ax.contour'''
'''函数图和等高线图,最好使用相同的颜色映射'''
'''设置 z 的显示区间,相当于二维图形中的 plt.xlim 函数'''
ax.set_zlim(-2, 2)
'''类似的,还有ax.set_xlim 和 ax.set_ylim'''
'''也可以侧向投影,将图像投影到 x=-4 所在平面'''
'''-----------------------------------------------------------------------'''
fg = plt.figure(num=2)
x = np.arange(-4, 4, 0.25)
y = np.arange(-4, 4, 0.25)
X, Y = np.meshgrid(x, y)
R = np.sqrt(X ** 2 + Y ** 2)
Z = np.sin(R)
ax = Axes3D(fg)
ax.plot_surface(X, Y, Z, rstride=2, cstride=2, cmap=plt.get_cmap('rainbow'))
ax.contourf(X, Y, Z, zdir='x', offset=-4, cmap=plt.get_cmap('rainbow'))
'''zdir='x' 和 offset=-4,表示投影到 x=-4 所在平面'''
ax.set_zlim(-2, 2)
plt.show()
输出
10 多合一显示
(1)subplot
import numpy as np
import matplotlib.pyplot as plt
plt.figure()
plt.subplot(2, 2, 1) # 将图划分成2行2列,且在1的位置出图
plt.plot([0, 1], [0, 1])
# 第一个[0, 1]表示,两个点的横坐标分别是0和1,第二个[0, 1]表示两个点的纵坐标分别是0和1
plt.xlabel('I am x')
plt.title('I am title 1')
plt.subplot(2, 2, 2)
plt.plot([0, 1], [0, 1])
plt.title('I am title 2')
plt.subplot(223) # 223是"2, 2, 3"的缩写
plt.plot([0, 1], [0, 3])
plt.title('I am title 3')
plt.subplot(224)
plt.plot([0, 1], [0, 4])
'''可以试一下plt.subplot(234)效果怎么样'''
'''-----------------------------------------------------------------------'''
plt.figure(num=2)
plt.subplot(2, 1, 1) # 将图划分成2行1列,且在1的位置出图
plt.plot([0, 1], [0, 1])
plt.subplot(2, 3, 4) # 将图划分成2行3列,且在4的位置出图
plt.plot([0, 1], [0, 1])
'''之所以要在4的位置出图,是因为1,2,3都被上一张图给占了'''
plt.show()
输出
(2)gridspec.GridSpec
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
'''-----------------------------------------------------------------------'''
plt.figure()
'''将整个图像窗口分成3行3列.'''
gs = gridspec.GridSpec(3, 3)
''' gs[0, :]表示这个图占第0行和所有列, gs[1, :2]表示这个图占第1行和第2列前的所有列'''
ax1 = plt.subplot(gs[0, :])
ax2 = plt.subplot(gs[1, :2])
ax3 = plt.subplot(gs[1:, 2])
''' gs[-1, 0]表示这个图占倒数第1行和第0列, gs[-1, -2]表示这个图占倒数第1行和倒数第2列.'''
ax4 = plt.subplot(gs[-1, 0])
ax5 = plt.subplot(gs[-1, -2])
plt.show()
输出
11 图中图
import numpy as np
import matplotlib.pyplot as plt
'''创建数据'''
x = [1, 2, 3, 4, 5, 6, 7]
y = [1, 3, 4, 2, 5, 8, 6]
fig = plt.figure()
'''定义大图的尺寸'''
left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
'''0.1表示10%,0.8表示80%,
left表示坐标图离窗口的左边框的距离占窗口的10%,也就是说左边的空白部分占窗口横向的10%
bottom表示坐标图离窗口的下边框的距离占窗口纵向的10%'''
ax1 = fig.add_axes([left, bottom, width, height])
ax1.plot(x, y, 'r') # r表示红色
ax1.set_xlabel('x') # 坐标轴标签
ax1.set_ylabel('y')
ax1.set_title('title')
'''绘制小图'''
left, bottom, width, height = 0.2, 0.6, 0.25, 0.25
ax2 = fig.add_axes([left, bottom, width, height])
ax2.plot(y, x, 'b') # 将原来的图形沿 y=x 对称
ax2.set_xlabel('x')
ax2.set_ylabel('y')
ax2.set_title('title inside 1')
'''可以使用更为简单的方式绘制小图'''
plt.axes([0.6, 0.2, 0.25, 0.25])
plt.plot(y[::-1], x, 'g') # 注意对y进行了逆序处理
plt.xlabel('x')
plt.ylabel('y')
plt.title('title inside 2')
plt.show()
输出
12 次坐标轴
import numpy as np
import matplotlib.pyplot as plt
'''所谓主次坐标轴指的是两条线段共享相同的横坐标,但却不共享纵坐标
这种情况一般让其中一条曲线的纵坐标轴位于左边,另一条曲线的纵坐标轴位于右边,
左右两条纵坐标轴分别称为 主次坐标轴'''
'''创建数据'''
x = np.arange(0, 10, 0.1)
y1 = 0.05 * x**2
y2 = -1 * y1 # y1与y2是相互倒置的
'''获取figure默认的坐标系 ax1'''
fig, ax1 = plt.subplots()
'''生成一个新的坐标系 ax2,它与 ax1 共享横坐标轴'''
ax2 = ax1.twinx()
'''绘图'''
ax1.plot(x, y1, 'g-') # green, solid line
ax1.set_xlabel('X data')
ax1.set_ylabel('Y1 data', color='g')
ax2.plot(x, y2, 'b--') # b-- 表示蓝色虚线
ax2.set_ylabel('Y2 data', color='b')
plt.show()
输出
13 动画
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation
fig, ax = plt.subplots()
'''我们的目的是绘制0-2*pi范围内的正弦曲线'''
'''创建数据'''
x = np.arange(0, 2*np.pi, 0.01)
line, = ax.plot(x, np.sin(x))
def animate(i):
'''构造自定义动画函数'''
line.set_ydata(np.sin(x + i/10.0))
return line,
def init():
'''构造初始帧函数'''
line.set_ydata(np.sin(x))
return line,
'''我们调用FuncAnimation函数生成动画'''
ani = animation.FuncAnimation(fig=fig,
func=animate,
frames=100,
init_func=init,
interval=20,
blit=False)
'''参数说明,fig用来指定需要绘制动画的窗口,
func 指定动画函数,
frames 动画长度,一次循环包含的帧数(更新次数),一次循环过后再执行下一次循环
init_func 开始帧函数,
interval 更新频率,以ms计,每隔多少毫秒更新一次
blit 如果每次更新都刷新所有点,那么就选择True,若选False,则只更新发生变化的点'''
'''动画时长 = frames x interval'''
plt.show()
'''保存动画'''
ani.save("test.gif", writer='pillow')
输出结果当前页面暂时无法呈现