Python使用Matplotlib库绘制双y轴图形(柱状图+折线图) - 知乎 (zhihu.com)

01基础用法基础用法

1
2
3
4
5
6
7
import numpy as np  
import matplotlib.pyplot as plt
x = np.linspace(-1, 1, 50)
# y = 2*x + 1
y = x**2
plt.plot(x, y) #绘制图像
plt.show() #图像展示

02figure图像

1
2
3
4
5
6
7
8
9
10
11
12
13
import matplotlib.pyplot as plt  
import numpy as np
x = np.linspace(-3, 3, 50)
y1 = 2*x + 1
y2 = x**2
plt.figure() #创建一个新的图形窗口
plt.plot(x, y1)


plt.figure(num=3, figsize=(8, 5))
plt.plot(x, y1)
plt.plot(x, y2, color='red', linewidth=1.0, linestyle='--')
plt.show()

03设置坐标轴1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import matplotlib.pyplot as plt  
import numpy as np
x = np.linspace(-3, 3, 50)
y1 = 2*x + 1
y2 = x**2
plt.figure() #创建一个新的图形窗口
plt.plot(x, y1)
plt.plot(x, y2, color='red', linewidth=1.0, linestyle='--')
plt.xlim((-1, 2)) #设置坐标轴范围
plt.ylim((-1, 2))
plt.xlabel('x') #设置x轴标签
plt.ylabel('y')
new_ticks = np.linspace(-1, 2, 5)
plt.xticks(new_ticks) #设置坐标轴的角标
plt.yticks([-2, -1.8, -1, 1.22, 3], [r'$really\ bad$', 'bad', 'normal', 'good', 'really good']) #r'$really\ bad$改变字体,空格前加\

plt.show()

04设置坐标轴2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import matplotlib.pyplot as plt  
import numpy as np
x = np.linspace(-3, 3, 50)
y1 = 2*x + 1
y2 = x**2
plt.figure() #创建一个新的图形窗口
plt.plot(x, y1)
plt.plot(x, y2, color='red', linewidth=1.0, linestyle='--')
ax = plt.gca() # 创建关于坐标轴的对象
ax.spines['right'].set_color('none') # 设置坐标轴无色
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom') # 设置下方为x轴,其实不用改
ax.yaxis.set_ticks_position('left') # 设置左方为y轴
ax.spines['bottom'].set_position(('data', 0)) # 'data'表示按数值挪动,其后数字代表挪动到Y轴的刻度值,除‘data’以外还有‘outward’和‘axes’
ax.spines['left'].set_position(('data', 0))
plt.show()

05图例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import matplotlib.pyplot as plt  
import numpy as np
x = np.linspace(-3, 3, 50)
y1 = 2*x + 1
y2 = x**2
plt.figure() #创建一个新的图形窗口
#方法1
# l1 = plt.plot(x, y1, label='up')
# l2 = plt.plot(x, y2, color='red', linewidth=1.0, linestyle='--', label='down')
# plt.legend() #显示图例
#方法2
l1, = plt.plot(x, y1)
l2, = plt.plot(x, y2, color='red', linewidth=1.0, linestyle='--')
plt.legend(handles=[l1, l2], labels=['aaa', 'bbb'], loc='best') # 显示图例 loc='best' 表示图例自动选择最佳位置
plt.show()

06添加注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import matplotlib.pyplot as plt  
import numpy as np
x = np.linspace(-3, 3, 50)
y1 = 2*x + 1
y2 = x**2
plt.figure() #创建一个新的图形窗口


l1 = plt.plot(x, y1, label='up')
l2 = plt.plot(x, y2, color='red', linewidth=1.0, linestyle='--', label='down')
plt.legend() #显示图例

#设置坐标轴
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))

#添加一个点与一条线
x0 = 1
y0 = 2*x0 + 1
plt.scatter(x0, y0, 10, 'b') # 绘制一个点,点的位置,大小,颜色是blue
plt.plot([x0, x0], [y0, 0], 'k--', lw=1) # 绘制一条直线,k是黑色,用虚线表示lw=linewidth

#方法1
plt.annotate('2X+1=%s' % y0, xy=(x0, y0), xycoords='data', xytext=(+30, -30), textcoords='offset points', fontsize=16, arrowprops=dict(arrowstyle='->', connectionstyle='arc3, rad=.2'))
#xycoords='data'表示注释点的坐标以数据的坐标(1,3)为准
#xytext=(+30, -30)表示注释文本的坐标相对注释点坐标(1,3)的位置
#textcoords='offset points'表示注释文本的坐标相对注释点坐标(1,3)的位置是以点为单位的,'offset pixels'表示以像素为单位
#fontsize注释字体大小
#arrowprops=dict(arrowstyle=‘->’, connectionstyle=‘arc3, rad=.2’)是一个参数,用来指定绘制一个箭头从文本到被注释点的属性12。它是一个字典,包含以下两个键值对:
#arrowstyle=‘->‘表示箭头的样式是一个简单的箭头,箭头尾部是一条直线,箭头头部是一个三角形12。你也可以使用其他的箭头样式,比如’-|>’(箭头尾部是一条直线,箭头头部是一个大三角形)或’<-'(箭头尾部是一个三角形,箭头头部是一条直线)12。
#connectionstyle=‘arc3, rad=.2’表示箭头的连接方式是一个三次贝塞尔曲线,rad=.2表示曲线的弯曲程度12。你也可以使用其他的连接方式,比如’angle3’(两条直线连接,中间有一个角度)或’bar’(两条直线连接,中间有一段水平或垂直的线段)12。

#方法2
plt.text(-1, 10, 'This is the some text', fontdict={'size': 16, 'color': 'y'})
plt.show()

07能见度tick

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import matplotlib.pyplot as plt  
import numpy as np
x = np.linspace(-3, 3, 50)
y1 = 2*x + 1
y2 = x**2
plt.figure() #创建一个新的图形窗口


l1 = plt.plot(x, y1, label='up')
l2 = plt.plot(x, y2, color='red', linewidth=1.0, linestyle='--', label='down')
plt.legend() #显示图例

#设置坐标轴
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))

#设置坐标的文本框
for label in ax.get_xticklabels() + ax.get_yticklabels():
label.set_fontsize(12) # 设置x轴和y轴上的刻度标签的字体大小为12
label.set_bbox(dict(facecolor='white', edgecolor='none', alpha=0.7)) #facecolor是文本框的背景颜色, edgecolor是文本框的边框颜色,alpha是文本框的透明度,取值范围是0到1,0表示完全透明,1表示完全不透明

plt.show()

08散点图

1
2
3
4
5
6
7
8
9
10
11
12
13
import matplotlib.pyplot as plt  
import numpy as np
n = 1024
X = np.random.normal(0, 1, n)
Y = np.random.normal(0, 1, n)
T = np.arctan2(Y, X)

plt.scatter(X, Y, s=75, c=T, alpha=0.5)
# plt.scatter(np.arange(5), np.arange(5))

plt.xticks(())
plt.yticks(())
plt.show()

09柱状图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import matplotlib.pyplot as plt  
import numpy as np

n = 12
x = np.arange(n)
y1 = (1-x/float(n))*np.random.uniform(0.5, 1.0, n) #0.5 到 1.0 的区间内,均匀地抽取 n 个随机数,然后返回一个长度为 n 的一维数组
y2 = (1-x/float(n))*np.random.uniform(0.5, 1.0, n)
plt.bar(x, +y1, facecolor='#9999ff', edgecolor='white')
plt.bar(x, -y2, facecolor='#ff9999', edgecolor='white')
for x_1, y_1 in zip(x, y1):
plt.text(x_1, y_1, '%.2f' % y_1, ha='center', va='bottom')
for x_2, y_2 in zip(x, y2):
plt.text(x_2, -y_2-0.12, '-%.2f' % y_2, ha='center', va='bottom')
# plt.xlim(-0.5, n)
# plt.ylim(-1.25, 1.25)
plt.axis([-0.5, n, -1.25, 1.25]) # 设置 x 轴和 y 轴的显示范围
plt.xticks(())
plt.yticks(())
plt.show()

10等高线图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import matplotlib.pyplot as plt  
import numpy as np


def f(x, y):
return (1 - x/2 + x**5 + y**3) * np.exp(-x**2 - y**2)
n = 256
x = np.linspace(-3, 3, n)
y = np.linspace(-3, 3, n)
X, Y = np.meshgrid(x, y)
plt.contourf(X, Y, f(X, Y), 8, alpha=0.75, cmap=plt.cm.hot)
# 绘制等高线填充图
# X, Y:表示网格的坐标点
# f(X, Y):表示计算每个坐标点的高度值
# 8:表示将等高线分成8个级别
# alpha=0.75:表示填充颜色的透明度为0.75
# cmap=plt.cm.hot:表示使用"hot"颜色映射,即红-黄-白的渐变色
C = plt.contour(X, Y, f(X, Y), 8, colors='black', linewidth=0.5)
#绘制的等高线图
#8表示您希望绘制的等高线数量
plt.clabel(C, inline=True, fontsize=10)
#添加高度标签
#C: 这是一个等高线对象,通常是通过plt.contour或plt.contourf函数生成的。
#inline=True: 表示将标签放置在线的中间位置。如果设置为False,标签将被放置在等高线线条旁边。
#fontsize=10: 这是标签的字体大小,可以根据需要调整。
plt.xticks(())
plt.yticks(())
plt.show()

11图片lmage

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import matplotlib.pyplot as plt  
import numpy as np
a = np.array([0.31, 0.36, 0.42, 0.36, 0.43, 0.52, 0.42, 0.52, 0.65]).reshape(3, 3)
plt.imshow(a, interpolation='nearest', cmap='bone', origin='lower')
#a是要绘制的矩阵或图像数据。
#interpolation='nearest'指定使用最近邻插值方法来显示图像。
# cmap='bone'指定使用'Bone'颜色映射来渲染图像,这将使图像呈现黑白效果。
# origin='lower'表示矩阵的原点在左下角。
plt.colorbar(shrink=1)
#添加颜色条。
# shrink=1表示将颜色条的尺寸设置为图像的1/1,使其与图像大小一致。
plt.xticks(())
plt.yticks(())
plt.show()

12三维数据绘图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# import matplotlib  
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D

# matplotlib.use('Qt5Agg')
fig = plt.figure()
#方法1
ax = fig.add_axes(Axes3D(fig)) #Axes3D类创建一个3D坐标轴对象ax,用来绘制3D图形
# ax = Axes3D(fig) #不能用了
#方法2
# ax = plt.axes(projection='3d')
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.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=plt.get_cmap('rainbow'))
#X,Y,Z 是三维数据的网格,分别表示 x、y 和 z 方向的坐标点。
#rstride 和 cstride 表示数据之间的步幅,用于控制绘制的密度,rstride 表示行步幅,cstride 表示列步幅。设置为1表示使用所有数据点进行绘制,较小的值会导致更密集的绘制,较大的值会导致更稀疏的绘制。
#cmap 是用于设置颜色映射的参数,它决定了表面图的颜色样式。在这里使用了 plt.get_cmap('rainbow'),它表示使用彩虹色的颜色映射,即高值用红色表示,低值用蓝色表示,中间值用绿色表示
plt.contourf(X, Y, Z, zdir='z', offset=-2, cmap=plt.get_cmap('rainbow'))
#zdir 参数指定了绘制的等高线图所在的平面,可以取值为 'x'、'y' 或 'z',分别表示绘制在 x、y 或 z 轴上。
#offset 参数用于指定绘制的等高线图所在平面的偏移位置,它是一个数值,用于控制等高线图所在平面的位置。
ax.set_zlim(-2, 2)
plt.show()

13多合一显示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import matplotlib.pyplot as plt  
import numpy as np
fig = plt.figure()
# plt.subplot(2, 2, 1) #分成两行两列,选第1个图
# plt.plot([0, 1], [0, 1])
# plt.subplot(2, 2, 2) #分成两行两列,选第2个图
# plt.plot([0, 1], [0, 2])
# plt.subplot(2, 2, 3) #分成两行两列,选第3个图
# plt.plot([0, 1], [0, 3])
# plt.subplot(2, 2, 4) #分成两行两列,选第4个图
# plt.plot([0, 1], [0, 4])

plt.subplot(2, 1, 1) #分成两行一列,选第1个图,但占3个位置
plt.plot([0, 1], [0, 1])
plt.subplot(2, 3, 4) #分成两行三列,选第4个图
plt.plot([0, 1], [0, 2])
plt.subplot(2, 3, 5) #分成两行三列,选第5个图
plt.plot([0, 1], [0, 3])
plt.subplot(2, 3, 6) #分成两行三列,选第6个图
plt.plot([0, 1], [0, 4])
plt.show()

14分格显示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import matplotlib.pyplot as plt  
import numpy as np
import matplotlib.gridspec as gridspec
#方法1
plt.figure()
ax1 = plt.subplot2grid((3, 3), (0, 0), colspan=3, rowspan=1)
#(3, 3):表示将图形区域分割为 3 行 3 列的网格。
#(0, 0):表示该子图位于第 0 行第 0 列的位置。
#colspan=3:表示该子图跨越 3 列,即宽度为 3。
#rowspan=1:表示该子图跨越 1 行,即高度为 1。
ax1.plot([1, 2], [1, 2])
# ax1.set_label('ax1')
ax1.set_title('ax1')
ax2 = plt.subplot2grid((3, 3), (1, 0), colspan=2)
ax3 = plt.subplot2grid((3, 3), (1, 2), rowspan=2)
ax4 = plt.subplot2grid((3, 3), (2, 0))
ax5 = plt.subplot2grid((3, 3), (2, 1))
#方法2
plt.figure()
gs = gridspec.GridSpec(3, 3)
ax6 = plt.subplot(gs[0, :]) #gs[0, :]:表示将子图放置在 GridSpec 对象 gs 的第 0 行的所有列上
ax7 = plt.subplot(gs[1, :2])
ax8 = plt.subplot(gs[1:, 2])
ax9 = plt.subplot(gs[-1, 0])
ax10 = plt.subplot(gs[-1, -2])
plt.show()

15图中图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import matplotlib.pyplot as plt  
import numpy as np
import matplotlib.gridspec as gridspec
fig = plt.figure()
fig.clf()
x = [1, 2, 3, 4, 5, 6, 7]
y = [1, 3, 4, 2, 5, 8, 6]

left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
ax1 = fig.add_axes([left, bottom, width, height])
#这个方法需要一个由4个元素组成的列表对象,分别对应图形的左、底、宽、高。每个数字必须在0和1之间,表示相对于图形的归一化坐标。
# 例如,left=0.1表示轴对象的左边缘距离图形的左边缘10%的宽度,width=0.8表示轴对象的宽度占图形的80%的宽度
ax1.plot(x, y, 'r')
ax1.set_xlabel('x')
ax1.set_ylabel('y')
ax1.set_title('title_1')

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')
ax2.plot(x, y, 'r')
ax2.set_xlabel('x')
ax2.set_ylabel('y')
ax2.set_title('title_2')

plt.axes([0.6, 0.2, 0.25, 0.25])
plt.plot(y[::-1], x, 'g')
plt.xlabel('x')
plt.ylabel('y')
plt.title('title_2')
plt.show()

16次坐标轴

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import matplotlib.pyplot as plt  
import numpy as np

x = np.arange(0, 10, 0.1)
y1 = 0.05*x**2
y2 = -1*y1
# 使用plt.subplots()创建一个图形对象fig和一个轴对象ax1,
fig, ax1 = plt.subplots()
# 使用ax1.twinx()创建一个与ax1共享x轴的轴对象ax2
ax2 = ax1.twinx()
ax1.plot(x, y1, 'g-')
ax2.plot(x, y2, 'b--')

ax1.set_xlabel('x')
ax1.set_ylabel('y1', c='g')
ax2.set_ylabel('y2', c='b')
plt.show()

17动画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import matplotlib.pyplot as plt  
import numpy as np
from matplotlib import animation

fig, ax = plt.subplots()
x = np.arange(0.2*np.pi, 0.01)
line, = ax.plot(x, np.sin(x))


def animations(i):
line.set_ydata(np.sin(x+i/10))
return line,


def init():
line.set_ydata(np.sin(x))
return line,


ani = animation.FuncAnimation(fig=fig, func=animations, frames=100, init_func=init, interval=20, blit=False)
plt.show()