matplotlib
# 基础知识
Matplotlib是Python中最流行的绘图库,提供了丰富的2D和3D绘图功能,是数据可视化的基础工具。
# 基本概念
# Figure and Axis
在Matplotlib中,Figure和Axis是两个重要的概念,它们分别代表了绘图的整个图像和图像上的一个子区域。
Figure(图像):
- Figure是整个绘图的最顶层容器,它包含了所有的绘图元素
- 可以通过
plt.figure()函数创建一个新的Figure对象 - 一个Figure对象可以包含多个子区域(Axis对象)
- Figure对象可以保存为图片文件,如PNG、PDF等格式
Axis(轴):
- Axis是Figure内部的一个子区域,包含坐标轴、刻度、标签以及绘图区域
- 每个Axis对象都有自己的X轴和Y轴
- 可以通过
ax.set_xlabel()、ax.set_ylabel()设置轴标签 - 可以通过
ax.set_xlim()、ax.set_ylim()设置轴的范围
# 基本绘图
import matplotlib.pyplot as plt
import numpy as np
# 创建简单的线图
x = np.linspace(0, 10, 100)
y = np.sin(x)
plt.figure(figsize=(8, 6))
plt.plot(x, y, 'b-', linewidth=2, label='sin(x)')
plt.xlabel('x')
plt.ylabel('y')
plt.title('正弦函数')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
# 创建子图
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
# 第一个子图
ax1.plot(x, np.sin(x), 'b-', label='sin(x)')
ax1.set_xlabel('x')
ax1.set_ylabel('y')
ax1.set_title('正弦函数')
ax1.legend()
ax1.grid(True, alpha=0.3)
# 第二个子图
ax2.plot(x, np.cos(x), 'r-', label='cos(x)')
ax2.set_xlabel('x')
ax2.set_ylabel('y')
ax2.set_title('余弦函数')
ax2.legend()
ax2.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
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
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
# 绘图样式设置
# 设置绘图样式
plt.style.use('seaborn-v0_8') # 使用seaborn样式
# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
# 设置图形大小和DPI
plt.figure(figsize=(10, 6), dpi=100)
# 设置颜色和线型
colors = ['red', 'blue', 'green', 'orange', 'purple']
line_styles = ['-', '--', '-.', ':', '-']
markers = ['o', 's', '^', 'D', 'v']
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 图表类型
# 1. 线图 (Line Plot)
# 基本线图
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)
plt.figure(figsize=(10, 6))
plt.plot(x, y1, 'b-', linewidth=2, label='sin(x)')
plt.plot(x, y2, 'r--', linewidth=2, label='cos(x)')
plt.xlabel('x')
plt.ylabel('y')
plt.title('三角函数')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
# 多线图
fig, axes = plt.subplots(2, 2, figsize=(12, 8))
# 子图1:基本线图
axes[0, 0].plot(x, y1)
axes[0, 0].set_title('基本线图')
# 子图2:带标记的线图
axes[0, 1].plot(x, y1, 'o-', markersize=4)
axes[0, 1].set_title('带标记的线图')
# 子图3:多条线
axes[1, 0].plot(x, y1, label='sin(x)')
axes[1, 0].plot(x, y2, label='cos(x)')
axes[1, 0].legend()
axes[1, 0].set_title('多条线')
# 子图4:填充区域
axes[1, 1].fill_between(x, y1, y2, alpha=0.3)
axes[1, 1].plot(x, y1, 'b-', label='sin(x)')
axes[1, 1].plot(x, y2, 'r-', label='cos(x)')
axes[1, 1].legend()
axes[1, 1].set_title('填充区域')
plt.tight_layout()
plt.show()
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
39
40
41
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
39
40
41
# 2. 散点图 (Scatter Plot)
# 基本散点图
np.random.seed(42)
x = np.random.randn(100)
y = np.random.randn(100)
colors = np.random.rand(100)
sizes = 1000 * np.random.rand(100)
plt.figure(figsize=(10, 6))
plt.scatter(x, y, c=colors, s=sizes, alpha=0.6, cmap='viridis')
plt.colorbar(label='颜色值')
plt.xlabel('x')
plt.ylabel('y')
plt.title('散点图')
plt.grid(True, alpha=0.3)
plt.show()
# 分类散点图
categories = np.random.choice(['A', 'B', 'C'], 100)
colors_map = {'A': 'red', 'B': 'blue', 'C': 'green'}
plt.figure(figsize=(10, 6))
for category in ['A', 'B', 'C']:
mask = categories == category
plt.scatter(x[mask], y[mask], c=colors_map[category],
label=category, alpha=0.7, s=50)
plt.xlabel('x')
plt.ylabel('y')
plt.title('分类散点图')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
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
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
# 3. 柱状图 (Bar Plot)
# 基本柱状图
categories = ['A', 'B', 'C', 'D', 'E']
values = [23, 45, 56, 78, 32]
plt.figure(figsize=(10, 6))
bars = plt.bar(categories, values, color='skyblue', alpha=0.7)
plt.xlabel('类别')
plt.ylabel('数值')
plt.title('基本柱状图')
# 在柱子上添加数值标签
for bar, value in zip(bars, values):
plt.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 1,
str(value), ha='center', va='bottom')
plt.grid(True, alpha=0.3, axis='y')
plt.show()
# 分组柱状图
categories = ['A', 'B', 'C', 'D']
group1 = [23, 45, 56, 78]
group2 = [34, 56, 67, 89]
x = np.arange(len(categories))
width = 0.35
plt.figure(figsize=(10, 6))
plt.bar(x - width/2, group1, width, label='组1', alpha=0.7)
plt.bar(x + width/2, group2, width, label='组2', alpha=0.7)
plt.xlabel('类别')
plt.ylabel('数值')
plt.title('分组柱状图')
plt.xticks(x, categories)
plt.legend()
plt.grid(True, alpha=0.3, axis='y')
plt.show()
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
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
# 4. 直方图 (Histogram)
# 基本直方图
data = np.random.normal(0, 1, 1000)
plt.figure(figsize=(12, 4))
plt.subplot(1, 3, 1)
plt.hist(data, bins=30, alpha=0.7, color='skyblue', edgecolor='black')
plt.xlabel('值')
plt.ylabel('频次')
plt.title('基本直方图')
plt.grid(True, alpha=0.3)
plt.subplot(1, 3, 2)
plt.hist(data, bins=30, alpha=0.7, color='lightgreen',
edgecolor='black', density=True)
plt.xlabel('值')
plt.ylabel('密度')
plt.title('密度直方图')
plt.grid(True, alpha=0.3)
plt.subplot(1, 3, 3)
plt.hist(data, bins=30, alpha=0.7, color='lightcoral',
edgecolor='black', cumulative=True)
plt.xlabel('值')
plt.ylabel('累积频次')
plt.title('累积直方图')
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
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
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
# 5. 饼图 (Pie Chart)
# 基本饼图
sizes = [30, 25, 20, 15, 10]
labels = ['A', 'B', 'C', 'D', 'E']
colors = ['lightblue', 'lightgreen', 'lightcoral', 'lightyellow', 'lightpink']
plt.figure(figsize=(10, 6))
plt.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%',
startangle=90, explode=(0.1, 0, 0, 0, 0))
plt.title('基本饼图')
plt.axis('equal')
plt.show()
# 环形图
plt.figure(figsize=(10, 6))
plt.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%',
startangle=90, pctdistance=0.85)
centre_circle = plt.Circle((0,0), 0.70, fc='white')
fig = plt.gcf()
fig.gca().add_artist(centre_circle)
plt.title('环形图')
plt.axis('equal')
plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 6. 箱线图 (Box Plot)
# 基本箱线图
data1 = np.random.normal(0, 1, 100)
data2 = np.random.normal(2, 1.5, 100)
data3 = np.random.normal(-1, 0.5, 100)
plt.figure(figsize=(10, 6))
plt.boxplot([data1, data2, data3], labels=['组1', '组2', '组3'])
plt.ylabel('值')
plt.title('基本箱线图')
plt.grid(True, alpha=0.3)
plt.show()
# 分组箱线图
group1 = [np.random.normal(0, 1, 50), np.random.normal(0, 1, 50)]
group2 = [np.random.normal(2, 1, 50), np.random.normal(2, 1, 50)]
plt.figure(figsize=(10, 6))
plt.boxplot(group1 + group2, labels=['A1', 'A2', 'B1', 'B2'])
plt.ylabel('值')
plt.title('分组箱线图')
plt.grid(True, alpha=0.3)
plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 7. 热力图 (Heatmap)
# 基本热力图
data = np.random.rand(10, 10)
plt.figure(figsize=(8, 6))
im = plt.imshow(data, cmap='viridis')
plt.colorbar(im)
plt.title('基本热力图')
plt.show()
# 相关性热力图
import pandas as pd
# 创建示例数据
np.random.seed(42)
df = pd.DataFrame(np.random.randn(100, 4), columns=['A', 'B', 'C', 'D'])
correlation_matrix = df.corr()
plt.figure(figsize=(8, 6))
im = plt.imshow(correlation_matrix, cmap='coolwarm', vmin=-1, vmax=1)
plt.colorbar(im)
# 添加数值标签
for i in range(len(correlation_matrix.columns)):
for j in range(len(correlation_matrix.columns)):
plt.text(j, i, f'{correlation_matrix.iloc[i, j]:.2f}',
ha='center', va='center')
plt.xticks(range(len(correlation_matrix.columns)), correlation_matrix.columns)
plt.yticks(range(len(correlation_matrix.columns)), correlation_matrix.columns)
plt.title('相关性热力图')
plt.show()
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
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
# 3D绘图
# 基础知识大纲
# 1. 3D坐标系概念
- X轴、Y轴、Z轴:三维空间的基本坐标轴
- 坐标点:(x, y, z) 表示三维空间中的位置
- 投影:3D图形在2D平面上的投影显示
# 2. 3D图形基本元素
- 3D线图:三维空间中的曲线
- 3D散点图:三维空间中的点集
- 3D表面图:三维空间中的曲面
- 3D等高线图:三维数据的等高线表示
# 3. 视角和投影
- 视角控制:azim(方位角)、elev(仰角)
- 投影类型:正交投影、透视投影
- 缩放和平移:3D图形的交互操作
# 4. 3D绘图基本步骤
- 创建3D轴:
ax = fig.add_subplot(111, projection='3d') - 准备数据:X, Y, Z坐标数据
- 选择绘图类型:plot、scatter、plot_surface等
- 设置视角和标签
- 显示图形
# 1. 3D线图
from mpl_toolkits.mplot3d import Axes3D
# 3D螺旋线
t = np.linspace(0, 10, 100)
x = np.cos(t)
y = np.sin(t)
z = t
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')
ax.plot(x, y, z, 'b-', linewidth=2)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.set_title('3D螺旋线')
plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 2. 3D散点图
# 3D散点图
np.random.seed(42)
x = np.random.randn(100)
y = np.random.randn(100)
z = np.random.randn(100)
colors = np.random.rand(100)
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')
scatter = ax.scatter(x, y, z, c=colors, cmap='viridis', s=50)
plt.colorbar(scatter)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.set_title('3D散点图')
plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 3. 3D表面图
# 3D表面图
x = np.linspace(-5, 5, 100)
y = np.linspace(-5, 5, 100)
X, Y = np.meshgrid(x, y)
Z = np.sin(np.sqrt(X**2 + Y**2))
fig = plt.figure(figsize=(12, 5))
# 表面图
ax1 = fig.add_subplot(121, projection='3d')
surf = ax1.plot_surface(X, Y, Z, cmap='viridis', alpha=0.8)
ax1.set_xlabel('X')
ax1.set_ylabel('Y')
ax1.set_zlabel('Z')
ax1.set_title('3D表面图')
fig.colorbar(surf, ax=ax1)
# 等高线图
ax2 = fig.add_subplot(122, projection='3d')
contour = ax2.contour3D(X, Y, Z, 50, cmap='viridis')
ax2.set_xlabel('X')
ax2.set_ylabel('Y')
ax2.set_zlabel('Z')
ax2.set_title('3D等高线图')
fig.colorbar(contour, ax=ax2)
plt.tight_layout()
plt.show()
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
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
# 高级特性
# 1. 自定义样式
# 自定义样式
plt.style.use('default') # 重置为默认样式
# 自定义颜色
custom_colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7']
# 自定义字体
plt.rcParams['font.family'] = 'serif'
plt.rcParams['font.size'] = 12
plt.rcParams['axes.titlesize'] = 14
plt.rcParams['axes.labelsize'] = 12
plt.rcParams['xtick.labelsize'] = 10
plt.rcParams['ytick.labelsize'] = 10
# 创建自定义样式图
fig, ax = plt.subplots(figsize=(10, 6))
x = np.linspace(0, 10, 100)
y = np.sin(x)
ax.plot(x, y, color=custom_colors[0], linewidth=2, label='sin(x)')
ax.plot(x, np.cos(x), color=custom_colors[1], linewidth=2, label='cos(x)')
ax.set_xlabel('x轴', fontsize=12)
ax.set_ylabel('y轴', fontsize=12)
ax.set_title('自定义样式图', fontsize=14, fontweight='bold')
ax.legend(fontsize=11)
ax.grid(True, alpha=0.3)
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
plt.show()
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
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
# 2. 子图布局
# 复杂的子图布局
fig = plt.figure(figsize=(15, 10))
# 使用GridSpec创建复杂布局
from matplotlib.gridspec import GridSpec
gs = GridSpec(3, 3, figure=fig)
# 主图(占据2x2区域)
ax_main = fig.add_subplot(gs[0:2, 0:2])
x = np.linspace(0, 10, 100)
ax_main.plot(x, np.sin(x), 'b-', label='sin(x)')
ax_main.plot(x, np.cos(x), 'r-', label='cos(x)')
ax_main.set_title('主图')
ax_main.legend()
ax_main.grid(True, alpha=0.3)
# 右侧小图
ax_right = fig.add_subplot(gs[0:2, 2])
ax_right.hist(np.random.normal(0, 1, 1000), bins=30, alpha=0.7)
ax_right.set_title('直方图')
# 底部小图
ax_bottom = fig.add_subplot(gs[2, :])
ax_bottom.scatter(np.random.rand(50), np.random.rand(50), alpha=0.7)
ax_bottom.set_title('散点图')
plt.tight_layout()
plt.show()
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
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
# 3. 动画
# 基本动画
from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots(figsize=(8, 6))
x = np.linspace(0, 10, 100)
line, = ax.plot([], [], 'b-', linewidth=2)
ax.set_xlim(0, 10)
ax.set_ylim(-1, 1)
ax.set_xlabel('x')
ax.set_ylabel('sin(x)')
ax.set_title('动画正弦波')
ax.grid(True, alpha=0.3)
def animate(frame):
y = np.sin(x + frame * 0.1)
line.set_data(x, y)
return line,
ani = FuncAnimation(fig, animate, frames=100, interval=50, blit=True)
plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 4. 交互式绘图
# 交互式绘图
from matplotlib.widgets import Slider, Button
fig, ax = plt.subplots(figsize=(10, 6))
plt.subplots_adjust(bottom=0.25)
x = np.linspace(0, 10, 100)
y = np.sin(x)
line, = ax.plot(x, y, 'b-', linewidth=2)
ax.set_xlabel('x')
ax.set_ylabel('sin(x)')
ax.set_title('交互式正弦波')
ax.grid(True, alpha=0.3)
# 添加滑块
ax_freq = plt.axes([0.25, 0.1, 0.65, 0.03])
freq_slider = Slider(ax_freq, '频率', 0.1, 2.0, valinit=1.0)
def update(val):
freq = freq_slider.val
line.set_ydata(np.sin(freq * x))
fig.canvas.draw_idle()
freq_slider.on_changed(update)
plt.show()
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 实际应用案例
# 1. 数据分析可视化
# 股票数据分析
# 股票数据分析
import pandas as pd
import yfinance as yf
# 获取股票数据
ticker = "AAPL"
stock_data = yf.download(ticker, start="2023-01-01", end="2023-12-31")
# 创建分析图
fig, axes = plt.subplots(2, 2, figsize=(15, 10))
# 价格走势
axes[0, 0].plot(stock_data.index, stock_data['Close'], 'b-', linewidth=1)
axes[0, 0].set_title(f'{ticker} 收盘价走势')
axes[0, 0].set_ylabel('价格 ($)')
axes[0, 0].grid(True, alpha=0.3)
# 成交量
axes[0, 1].bar(stock_data.index, stock_data['Volume'], alpha=0.7, color='green')
axes[0, 1].set_title('成交量')
axes[0, 1].set_ylabel('成交量')
axes[0, 1].grid(True, alpha=0.3)
# 日收益率分布
daily_returns = stock_data['Close'].pct_change().dropna()
axes[1, 0].hist(daily_returns, bins=50, alpha=0.7, color='orange')
axes[1, 0].set_title('日收益率分布')
axes[1, 0].set_xlabel('收益率')
axes[1, 0].set_ylabel('频次')
axes[1, 0].grid(True, alpha=0.3)
# 移动平均线
ma_20 = stock_data['Close'].rolling(window=20).mean()
ma_50 = stock_data['Close'].rolling(window=50).mean()
axes[1, 1].plot(stock_data.index, stock_data['Close'], 'b-', label='收盘价', alpha=0.7)
axes[1, 1].plot(stock_data.index, ma_20, 'r-', label='20日均线', linewidth=2)
axes[1, 1].plot(stock_data.index, ma_50, 'g-', label='50日均线', linewidth=2)
axes[1, 1].set_title('移动平均线')
axes[1, 1].legend()
axes[1, 1].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
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
39
40
41
42
43
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
39
40
41
42
43
# 时间序列分析
# 时间序列分析
def time_series_analysis():
# 生成时间序列数据
dates = pd.date_range('2023-01-01', periods=365, freq='D')
np.random.seed(42)
# 趋势 + 季节性 + 噪声
trend = np.linspace(0, 10, 365)
seasonal = 5 * np.sin(2 * np.pi * np.arange(365) / 365)
noise = np.random.normal(0, 1, 365)
data = trend + seasonal + noise
# 创建时间序列图
fig, axes = plt.subplots(2, 2, figsize=(15, 10))
# 原始数据
axes[0, 0].plot(dates, data, 'b-', linewidth=1)
axes[0, 0].set_title('原始时间序列')
axes[0, 0].set_ylabel('值')
axes[0, 0].grid(True, alpha=0.3)
# 趋势分解
from scipy import signal
detrended = signal.detrend(data)
axes[0, 1].plot(dates, detrended, 'g-', linewidth=1)
axes[0, 1].set_title('去趋势数据')
axes[0, 1].set_ylabel('值')
axes[0, 1].grid(True, alpha=0.3)
# 自相关图
from statsmodels.graphics.tsaplots import plot_acf
plot_acf(data, ax=axes[1, 0], lags=40)
axes[1, 0].set_title('自相关函数')
# 功率谱密度
from scipy import signal
freqs, psd = signal.welch(data)
axes[1, 1].semilogy(freqs, psd)
axes[1, 1].set_title('功率谱密度')
axes[1, 1].set_xlabel('频率')
axes[1, 1].set_ylabel('功率谱密度')
axes[1, 1].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# time_series_analysis() # 需要安装statsmodels
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
39
40
41
42
43
44
45
46
47
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
39
40
41
42
43
44
45
46
47
# 2. 机器学习结果可视化
# 分类结果可视化
# 分类结果可视化
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import confusion_matrix, classification_report
# 生成数据
X, y = make_classification(n_samples=1000, n_features=2, n_redundant=0,
n_informative=2, random_state=42, n_clusters_per_class=1)
# 训练模型
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
model = LogisticRegression()
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
# 可视化结果
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
# 散点图
scatter = axes[0].scatter(X_test[:, 0], X_test[:, 1], c=y_test, cmap='viridis', alpha=0.7)
axes[0].set_title('真实标签')
axes[0].set_xlabel('特征1')
axes[0].set_ylabel('特征2')
plt.colorbar(scatter, ax=axes[0])
# 预测结果
scatter = axes[1].scatter(X_test[:, 0], X_test[:, 1], c=y_pred, cmap='viridis', alpha=0.7)
axes[1].set_title('预测标签')
axes[1].set_xlabel('特征1')
axes[1].set_ylabel('特征2')
plt.colorbar(scatter, ax=axes[1])
# 混淆矩阵
cm = confusion_matrix(y_test, y_pred)
im = axes[2].imshow(cm, cmap='Blues', interpolation='nearest')
axes[2].set_title('混淆矩阵')
axes[2].set_xlabel('预测标签')
axes[2].set_ylabel('真实标签')
# 添加数值标签
for i in range(2):
for j in range(2):
axes[2].text(j, i, str(cm[i, j]), ha='center', va='center')
plt.tight_layout()
plt.show()
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
39
40
41
42
43
44
45
46
47
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
39
40
41
42
43
44
45
46
47
# 回归结果可视化
# 回归结果可视化
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score, mean_squared_error
# 生成回归数据
np.random.seed(42)
X = np.random.rand(100, 1) * 10
y = 2 * X.flatten() + 1 + np.random.normal(0, 1, 100)
# 训练模型
model = LinearRegression()
model.fit(X, y)
y_pred = model.predict(X)
# 可视化结果
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
# 散点图和回归线
axes[0, 0].scatter(X, y, alpha=0.7, label='数据点')
axes[0, 0].plot(X, y_pred, 'r-', linewidth=2, label='回归线')
axes[0, 0].set_xlabel('X')
axes[0, 0].set_ylabel('y')
axes[0, 0].set_title('回归结果')
axes[0, 0].legend()
axes[0, 0].grid(True, alpha=0.3)
# 残差图
residuals = y - y_pred
axes[0, 1].scatter(y_pred, residuals, alpha=0.7)
axes[0, 1].axhline(y=0, color='r', linestyle='--')
axes[0, 1].set_xlabel('预测值')
axes[0, 1].set_ylabel('残差')
axes[0, 1].set_title('残差图')
axes[0, 1].grid(True, alpha=0.3)
# 残差分布
axes[1, 0].hist(residuals, bins=20, alpha=0.7, edgecolor='black')
axes[1, 0].set_xlabel('残差')
axes[1, 0].set_ylabel('频次')
axes[1, 0].set_title('残差分布')
axes[1, 0].grid(True, alpha=0.3)
# Q-Q图
from scipy import stats
stats.probplot(residuals, dist="norm", plot=axes[1, 1])
axes[1, 1].set_title('Q-Q图')
plt.tight_layout()
plt.show()
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
39
40
41
42
43
44
45
46
47
48
49
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
39
40
41
42
43
44
45
46
47
48
49
# 3. 科学计算可视化
# 偏微分方程可视化
# 偏微分方程可视化
from scipy.integrate import solve_bvp
import numpy as np
# 求解热传导方程
def heat_equation():
def fun(x, y):
return np.vstack((y[1], -np.exp(y[0])))
def bc(ya, yb):
return np.array([ya[0], yb[0] - np.log(2)])
x = np.linspace(1, 2, 25)
y = np.zeros((2, x.size))
y[0] = np.log(x)
sol = solve_bvp(fun, bc, x, y)
# 可视化结果
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
# 数值解
axes[0].plot(sol.x, sol.y[0], 'b-', linewidth=2, label='数值解')
axes[0].plot(x, np.log(x), 'r--', linewidth=2, label='解析解')
axes[0].set_xlabel('x')
axes[0].set_ylabel('y')
axes[0].set_title('热传导方程解')
axes[0].legend()
axes[0].grid(True, alpha=0.3)
# 误差
error = np.abs(sol.y[0] - np.log(sol.x))
axes[1].semilogy(sol.x, error, 'g-', linewidth=2)
axes[1].set_xlabel('x')
axes[1].set_ylabel('误差')
axes[1].set_title('数值误差')
axes[1].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
heat_equation()
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
39
40
41
42
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
39
40
41
42
# 信号处理可视化
# 信号处理可视化
def signal_processing_visualization():
# 生成信号
t = np.linspace(0, 1, 1000)
signal = np.sin(2 * np.pi * 10 * t) + 0.5 * np.sin(2 * np.pi * 50 * t)
noisy_signal = signal + 0.1 * np.random.randn(len(t))
# 傅里叶变换
from scipy.fft import fft, fftfreq
fft_signal = fft(noisy_signal)
freqs = fftfreq(len(t), t[1] - t[0])
# 可视化
fig, axes = plt.subplots(2, 2, figsize=(12, 8))
# 原始信号
axes[0, 0].plot(t, signal, 'b-', linewidth=1, label='原始信号')
axes[0, 0].set_xlabel('时间')
axes[0, 0].set_ylabel('幅度')
axes[0, 0].set_title('原始信号')
axes[0, 0].legend()
axes[0, 0].grid(True, alpha=0.3)
# 含噪声信号
axes[0, 1].plot(t, noisy_signal, 'r-', linewidth=1, label='含噪声信号')
axes[0, 1].set_xlabel('时间')
axes[0, 1].set_ylabel('幅度')
axes[0, 1].set_title('含噪声信号')
axes[0, 1].legend()
axes[0, 1].grid(True, alpha=0.3)
# 频谱
positive_freqs = freqs[:len(freqs)//2]
positive_fft = np.abs(fft_signal[:len(freqs)//2])
axes[1, 0].plot(positive_freqs, positive_fft, 'g-', linewidth=1)
axes[1, 0].set_xlabel('频率 (Hz)')
axes[1, 0].set_ylabel('幅度')
axes[1, 0].set_title('频谱')
axes[1, 0].grid(True, alpha=0.3)
# 滤波后的信号
# 简单的低通滤波
cutoff_freq = 20
fft_filtered = fft_signal.copy()
fft_filtered[np.abs(freqs) > cutoff_freq] = 0
filtered_signal = np.real(np.fft.ifft(fft_filtered))
axes[1, 1].plot(t, filtered_signal, 'm-', linewidth=1, label='滤波后信号')
axes[1, 1].plot(t, signal, 'b--', linewidth=1, label='原始信号')
axes[1, 1].set_xlabel('时间')
axes[1, 1].set_ylabel('幅度')
axes[1, 1].set_title('滤波后信号')
axes[1, 1].legend()
axes[1, 1].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
signal_processing_visualization()
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# 4. 数据故事化
# 数据故事化
def data_storytelling():
# 创建一个完整的数据故事
fig = plt.figure(figsize=(16, 12))
gs = GridSpec(3, 3, figure=fig)
# 标题
fig.suptitle('数据故事:气候变化趋势分析', fontsize=16, fontweight='bold')
# 1. 问题引入
ax_intro = fig.add_subplot(gs[0, :])
years = np.arange(1950, 2024)
temp_anomaly = 0.5 + 0.02 * (years - 1950) + 0.1 * np.sin(2*np.pi*(years-1950)/11)
ax_intro.plot(years, temp_anomaly, 'r-', linewidth=2, label='温度异常')
ax_intro.fill_between(years, temp_anomaly, alpha=0.3, color='red')
ax_intro.set_title('全球温度异常趋势(1950-2023)')
ax_intro.set_ylabel('温度异常 (°C)')
ax_intro.grid(True, alpha=0.3)
ax_intro.legend()
# 2. 详细分析
ax_detail = fig.add_subplot(gs[1, 0:2])
recent_years = years[-30:]
recent_temp = temp_anomaly[-30:]
ax_detail.plot(recent_years, recent_temp, 'b-', linewidth=2, marker='o')
ax_detail.set_title('最近30年趋势')
ax_detail.set_ylabel('温度异常 (°C)')
ax_detail.grid(True, alpha=0.3)
# 3. 季节性分析
ax_seasonal = fig.add_subplot(gs[1, 2])
months = np.arange(1, 13)
seasonal_pattern = 0.1 * np.sin(2*np.pi*(months-1)/12)
ax_seasonal.plot(months, seasonal_pattern, 'g-', linewidth=2, marker='s')
ax_seasonal.set_title('季节性模式')
ax_seasonal.set_xlabel('月份')
ax_seasonal.grid(True, alpha=0.3)
# 4. 预测
ax_forecast = fig.add_subplot(gs[2, :])
future_years = np.arange(2024, 2050)
forecast = 0.5 + 0.02 * (future_years - 1950) + 0.1 * np.sin(2*np.pi*(future_years-1950)/11)
ax_forecast.plot(years, temp_anomaly, 'b-', linewidth=2, label='历史数据')
ax_forecast.plot(future_years, forecast, 'r--', linewidth=2, label='预测')
ax_forecast.fill_between(future_years, forecast-0.1, forecast+0.1, alpha=0.3, color='red')
ax_forecast.set_title('未来预测(2024-2050)')
ax_forecast.set_xlabel('年份')
ax_forecast.set_ylabel('温度异常 (°C)')
ax_forecast.legend()
ax_forecast.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
data_storytelling()
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# 扩展资源
# 1. 相关库
- Seaborn: 基于Matplotlib的统计数据可视化库
- Plotly: 交互式绘图库
- Bokeh: 现代Web浏览器绘图库
- Altair: 声明式统计可视化库
- PyViz: 高级可视化工具集
# 2. 学习资源
- 官方文档: https://matplotlib.org/
- Matplotlib教程: https://matplotlib.org/stable/tutorials/
- Matplotlib示例: https://matplotlib.org/stable/gallery/
- Matplotlib中文文档: https://matplotlib.org.cn/
# 3. 社区资源
- Stack Overflow: Matplotlib相关问题
- GitHub: Matplotlib源码和示例
- Reddit: r/Python和r/DataVisualization
- Discord: Python和科学计算社区
# link
上次更新: 2025/10/08, 16:24:59