Matplotlib 是 Python 中最基础、最流行的数据可视化库。它提供了完整的 2D 绘图系统(部分 3D 支持),可以生成出版质量级别的图表,几乎可以绘制任何类型的图表。
# 基础安装pip install matplotlib# 使用 condaconda install matplotlib# 安装完整功能(包括可选依赖)pip install matplotlib[complete]# 标准导入方式import matplotlib.pyplot as pltimport numpy as np# 设置中文显示(可选)plt.rcParams['font.sans-serif'] = ['Arial Unicode MS', 'SimHei']plt.rcParams['axes.unicode_minus'] = False# Jupyter Notebook 中内嵌显示%matplotlib inlineimport matplotlib.pyplot as pltimport numpy as np# 准备数据x = np.linspace(0, 10, 100)y = np.sin(x)# 创建图表plt.figure(figsize=(10, 6))# 绘图plt.plot(x, y)# 添加标签plt.xlabel('x')plt.ylabel('sin(x)')plt.title('正弦函数')# 显示图表plt.show()# 创建图形和坐标轴fig, ax = plt.subplots(figsize=(10, 6))# 在坐标轴上绘图ax.plot(x, y, label='sin(x)')ax.plot(x, np.cos(x), label='cos(x)')# 设置属性ax.set_xlabel('x')ax.set_ylabel('y')ax.set_title('三角函数')ax.legend()ax.grid(True)plt.show()# 基础折线图x = [1, 2, 3, 4, 5]y = [2, 4, 6, 8, 10]plt.figure(figsize=(10, 6))plt.plot(x, y, marker='o', linestyle='-', color='blue', label='数据线')plt.xlabel('X 轴')plt.ylabel('Y 轴')plt.title('折线图示例')plt.legend()plt.grid(True)plt.show()# 多条折线x = np.linspace(0, 10, 100)fig, ax = plt.subplots(figsize=(10, 6))ax.plot(x, np.sin(x), label='sin(x)', color='blue')ax.plot(x, np.cos(x), label='cos(x)', color='red')ax.plot(x, np.tan(x), label='tan(x)', color='green')ax.set_ylim(-2, 2) # 限制 y 轴范围ax.legend()ax.set_title('三角函数对比')plt.show()# 基础散点图x = np.random.randn(100)y = np.random.randn(100)colors = np.random.rand(100)sizes = np.random.rand(100) * 1000plt.figure(figsize=(10, 6))plt.scatter(x, y, c=colors, s=sizes, alpha=0.5, cmap='viridis')plt.xlabel('X 值')plt.ylabel('Y 值')plt.title('散点图示例')plt.colorbar(label='颜色值')plt.show()# 分类散点图fig, ax = plt.subplots(figsize=(10, 6))for i, (label, color) inenumerate([('A', 'red'), ('B', 'blue'), ('C', 'green')]): x = np.random.randn(50) + i y = np.random.randn(50) + i ax.scatter(x, y, label=label, color=color, alpha=0.6)ax.legend()ax.set_title('分类散点图')plt.show()# 垂直柱状图categories = ['A', 'B', 'C', 'D', 'E']values = [23, 45, 56, 78, 32]fig, ax = plt.subplots(figsize=(10, 6))ax.bar(categories, values, color='skyblue', edgecolor='black')ax.set_xlabel('类别')ax.set_ylabel('数值')ax.set_title('柱状图示例')plt.show()# 分组柱状图x = np.arange(5)width = 0.35y1 = [20, 35, 30, 35, 27]y2 = [25, 32, 34, 20, 25]fig, ax = plt.subplots(figsize=(10, 6))ax.bar(x - width/2, y1, width, label='2023', color='blue')ax.bar(x + width/2, y2, width, label='2024', color='orange')ax.set_xticks(x)ax.set_xticklabels(['A', 'B', 'C', 'D', 'E'])ax.legend()ax.set_title('分组柱状图')plt.show()# 堆叠柱状图fig, ax = plt.subplots(figsize=(10, 6))ax.bar(categories, y1, label='产品A', color='blue')ax.bar(categories, y2, bottom=y1, label='产品B', color='orange')ax.legend()ax.set_title('堆叠柱状图')plt.show()# 水平柱状图fig, ax = plt.subplots(figsize=(10, 6))ax.barh(categories, values, color='lightcoral')ax.set_xlabel('数值')ax.set_title('水平柱状图')plt.show()# 基础直方图data = np.random.randn(1000)fig, ax = plt.subplots(figsize=(10, 6))ax.hist(data, bins=30, color='green', alpha=0.7, edgecolor='black')ax.set_xlabel('值')ax.set_ylabel('频数')ax.set_title('直方图示例')plt.show()# 多个分布对比data1 = np.random.normal(0, 1, 1000)data2 = np.random.normal(2, 1, 1000)fig, ax = plt.subplots(figsize=(10, 6))ax.hist(data1, bins=30, alpha=0.5, label='分布1', color='blue')ax.hist(data2, bins=30, alpha=0.5, label='分布2', color='red')ax.legend()ax.set_title('分布对比')plt.show()# 堆叠直方图fig, ax = plt.subplots(figsize=(10, 6))ax.hist([data1, data2], bins=30, stacked=True, label=['分布1', '分布2'])ax.legend()ax.set_title('堆叠直方图')plt.show()# 基础饼图labels = ['A', 'B', 'C', 'D']sizes = [15, 30, 45, 10]colors = ['gold', 'yellowgreen', 'lightcoral', 'lightskyblue']explode = (0, 0.1, 0, 0) # 突出显示第二块fig, ax = plt.subplots(figsize=(8, 8))ax.pie(sizes, explode=explode, labels=labels, colors=colors, autopct='%1.1f%%', shadow=True, startangle=90)ax.axis('equal') # 使饼图是圆形ax.set_title('饼图示例')plt.show()# 环形图fig, ax = plt.subplots(figsize=(8, 8))ax.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%', pctdistance=0.85, startangle=90)# 绘制中心圆centre_circle = plt.Circle((0, 0), 0.70, fc='white')ax.add_artist(centre_circle)ax.axis('equal')ax.set_title('环形图示例')plt.show()# 基础箱线图data = [np.random.normal(0, std, 100) for std inrange(1, 4)]fig, ax = plt.subplots(figsize=(10, 6))ax.boxplot(data, labels=['A', 'B', 'C'])ax.set_xlabel('类别')ax.set_ylabel('值')ax.set_title('箱线图示例')plt.show()# 水平箱线图fig, ax = plt.subplots(figsize=(10, 6))ax.boxplot(data, labels=['A', 'B', 'C'], vert=False)ax.set_xlabel('值')ax.set_title('水平箱线图')plt.show()# 箱线图与散点结合fig, ax = plt.subplots(figsize=(10, 6))bp = ax.boxplot(data, labels=['A', 'B', 'C'])# 添加散点for i, d inenumerate(data): y = d x = np.random.normal(i+1, 0.04, size=len(d)) ax.plot(x, y, 'r.', alpha=0.3)ax.set_title('箱线图 + 散点')plt.show()# 生成相关矩阵data = np.random.randn(10, 10)corr = np.corrcoef(data)fig, ax = plt.subplots(figsize=(10, 8))im = ax.imshow(corr, cmap='coolwarm', aspect='auto')ax.set_xticks(range(10))ax.set_yticks(range(10))ax.set_xticklabels(range(1, 11))ax.set_yticklabels(range(1, 11))plt.colorbar(im, label='相关系数')ax.set_title('热力图示例')plt.show()# 带注释的热力图fig, ax = plt.subplots(figsize=(10, 8))im = ax.imshow(corr, cmap='RdYlGn')for i inrange(len(corr)):for j inrange(len(corr)): text = ax.text(j, i, f'{corr[i, j]:.2f}', ha="center", va="center", color="black")plt.colorbar(im)ax.set_title('带注释的热力图')plt.show()# 基础面积图x = np.arange(10)y1 = np.random.randint(1, 10, 10)y2 = np.random.randint(1, 10, 10)fig, ax = plt.subplots(figsize=(10, 6))ax.stackplot(x, y1, y2, labels=['A', 'B'], alpha=0.8)ax.set_xlabel('X')ax.set_ylabel('Y')ax.legend(loc='upper left')ax.set_title('堆叠面积图')plt.show()# 填充区域x = np.linspace(0, 10, 100)y1 = np.sin(x)y2 = np.cos(x)fig, ax = plt.subplots(figsize=(10, 6))ax.plot(x, y1, label='sin(x)')ax.plot(x, y2, label='cos(x)')ax.fill_between(x, y1, y2, alpha=0.3, label='填充区域')ax.legend()ax.set_title('填充区域图')plt.show()x = np.arange(5)y = [20, 35, 30, 35, 27]error = [2, 3, 4, 2, 3]fig, ax = plt.subplots(figsize=(10, 6))ax.errorbar(x, y, yerr=error, fmt='o', color='blue', ecolor='red', elinewidth=2, capsize=5)ax.set_xlabel('类别')ax.set_ylabel('值')ax.set_title('误差棒图示例')plt.show()# 极坐标折线图theta = np.linspace(0, 2*np.pi, 100)r = 2 * np.sin(3*theta)fig, ax = plt.subplots(figsize=(8, 8), subplot_kw=dict(projection='polar'))ax.plot(theta, r, color='blue', linewidth=2)ax.fill(theta, r, alpha=0.3)ax.set_title('极坐标图示例', pad=20)plt.show()# 雷达图categories = ['A', 'B', 'C', 'D', 'E']values = [4, 3, 5, 4, 2]values += values[:1] # 闭合angles = np.linspace(0, 2*np.pi, len(categories), endpoint=False)angles = np.concatenate((angles, [angles[0]]))fig, ax = plt.subplots(figsize=(8, 8), subplot_kw=dict(projection='polar'))ax.plot(angles, values, 'o-', linewidth=2)ax.fill(angles, values, alpha=0.25)ax.set_xticks(angles[:-1])ax.set_xticklabels(categories)ax.set_title('雷达图示例', pad=20)plt.show()# 创建多个子图fig, axes = plt.subplots(2, 2, figsize=(12, 10))# 第一个子图axes[0, 0].plot([1, 2, 3], [1, 4, 9])axes[0, 0].set_title('折线图')# 第二个子图axes[0, 1].scatter([1, 2, 3], [1, 4, 9])axes[0, 1].set_title('散点图')# 第三个子图axes[1, 0].bar(['A', 'B', 'C'], [3, 5, 2])axes[1, 0].set_title('柱状图')# 第四个子图axes[1, 1].hist(np.random.randn(100), bins=20)axes[1, 1].set_title('直方图')plt.tight_layout() # 自动调整布局plt.show()# 使用 GridSpecfig = plt.figure(figsize=(12, 8))gs = fig.add_gridspec(3, 3)# 大图(占前两行和前两列)ax1 = fig.add_subplot(gs[0:2, 0:2])ax1.plot(np.random.randn(50))ax1.set_title('大图')# 右上角小图ax2 = fig.add_subplot(gs[0, 2])ax2.bar(['A', 'B'], [3, 5])ax2.set_title('右上小图')# 右中图ax3 = fig.add_subplot(gs[1, 2])ax3.scatter(np.random.randn(20), np.random.randn(20))ax3.set_title('右中图')# 底部长条图ax4 = fig.add_subplot(gs[2, :])ax4.plot(np.random.randn(100))ax4.set_title('底部图')plt.tight_layout()plt.show()from mpl_toolkits.axes_grid1.inset_locator import inset_axesfig, ax = plt.subplots(figsize=(10, 6))# 主图x = np.linspace(0, 10, 100)ax.plot(x, np.sin(x), label='sin(x)')ax.plot(x, np.cos(x), label='cos(x)')ax.legend()ax.set_title('主图')# 嵌套小图axins = inset_axes(ax, width="40%", height="30%", loc='upper right')axins.plot(x, np.sin(x), color='red')axins.set_xlim(0, 2)axins.set_ylim(-0.2, 1)axins.set_title('放大视图')plt.show()# 查看可用样式print(plt.style.available)# 使用样式plt.style.use('seaborn-v0_8-darkgrid')# 临时使用样式with plt.style.context('ggplot'): plt.plot([1, 2, 3], [1, 4, 9]) plt.title('临时使用 ggplot 样式') plt.show()# 颜色设置方式fig, ax = plt.subplots(figsize=(10, 6))x = np.arange(5)# 颜色名称ax.bar(x, [1, 2, 3, 4, 5], color=['red', 'blue', 'green', 'orange', 'purple'])# 十六进制颜色# ax.plot(x, y, color='#1f77b4')# RGB 元组# ax.plot(x, y, color=(0.1, 0.2, 0.5))# RGBA(带透明度)# ax.plot(x, y, color=(0.1, 0.2, 0.5, 0.7))# 灰度# ax.plot(x, y, color='0.5')plt.show()fig, ax = plt.subplots(figsize=(12, 6))x = np.arange(10)# 线型: '-', '--', '-.', ':', 'None', ' ', ''ax.plot(x, x+1, linestyle='-', label='实线')ax.plot(x, x+2, linestyle='--', label='虚线')ax.plot(x, x+3, linestyle='-.', label='点划线')ax.plot(x, x+4, linestyle=':', label='点线')# 标记: 'o', 's', '^', 'v', '<', '>', 'p', '*', 'h', '+', 'x', 'D'ax.plot(x, x+6, marker='o', linestyle='None', label='圆形标记')ax.plot(x, x+7, marker='s', linestyle='None', label='方形标记')ax.plot(x, x+8, marker='^', linestyle='None', label='三角标记')ax.legend()ax.set_title('线型与标记')plt.show()fig, ax = plt.subplots(figsize=(10, 6))x = np.linspace(0, 10, 100)ax.plot(x, np.sin(x))# 标题和标签ax.set_title('标题', fontsize=16, fontweight='bold')ax.set_xlabel('X 轴标签', fontsize=12)ax.set_ylabel('Y 轴标签', fontsize=12)# 文本注释ax.text(5, 0.5, '文本注释', fontsize=12, bbox=dict(facecolor='yellow', alpha=0.5))# 箭头注释ax.annotate('峰值', xy=(1.57, 1), xytext=(3, 0.5), arrowprops=dict(facecolor='black', shrink=0.05))# 数学公式(使用 LaTeX)ax.text(7, 0.5, r'$\sin(x) = \sum_{n=0}^{\infty} \frac{(-1)^n}{(2n+1)!}x^{2n+1}$', fontsize=12)plt.show()fig, ax = plt.subplots(figsize=(10, 6))x = np.linspace(0, 10, 100)ax.plot(x, np.sin(x), label='sin(x)', linewidth=2)ax.plot(x, np.cos(x), label='cos(x)', linewidth=2)ax.plot(x, np.tan(x), label='tan(x)', linewidth=2)# 图例位置ax.legend(loc='upper right') # 'best', 'upper right', 'upper left', 'lower left' 等# 自定义图例ax.legend( loc='upper left', fontsize=12, framealpha=0.9, shadow=True, fancybox=True, ncol=3# 多列)ax.set_ylim(-2, 2)plt.show()fig, ax = plt.subplots(figsize=(10, 6))x = np.linspace(0, 10, 100)ax.plot(x, np.sin(x))# 网格ax.grid(True, linestyle='--', alpha=0.5)# ax.grid(False) # 关闭网格# 仅主网格/次网格ax.grid(which='major', linestyle='-', linewidth='0.5', color='gray')ax.grid(which='minor', linestyle=':', linewidth='0.5', color='gray')ax.minorticks_on()# 坐标轴范围ax.set_xlim(0, 10)ax.set_ylim(-1.5, 1.5)# 对数坐标# ax.set_yscale('log')# ax.set_xscale('log')# 双Y轴ax2 = ax.twinx()ax2.plot(x, x, color='red', label='线性')ax2.set_ylabel('右侧 Y 轴')plt.show()from mpl_toolkits.mplot3d import Axes3D# 3D 曲面图fig = plt.figure(figsize=(12, 6))# 第一个图:3D 折线ax1 = fig.add_subplot(121, projection='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))ax1.plot_surface(X, Y, Z, cmap='viridis')ax1.set_title('3D 曲面图')# 第二个图:3D 散点ax2 = fig.add_subplot(122, projection='3d')x = np.random.randn(100)y = np.random.randn(100)z = np.random.randn(100)colors = np.random.rand(100)ax2.scatter(x, y, z, c=colors, cmap='coolwarm')ax2.set_title('3D 散点图')plt.tight_layout()plt.show()# 3D 等高线图fig = plt.figure(figsize=(10, 8))ax = fig.add_subplot(111, projection='3d')ax.plot_surface(X, Y, Z, cmap='viridis', alpha=0.8)ax.contour(X, Y, Z, zdir='z', offset=-2, cmap='coolwarm')ax.set_zlim(-2, 2)ax.set_title('3D 等高线图')plt.show()import pandas as pd# 创建示例数据df = pd.DataFrame({'Date': pd.date_range('2024-01-01', periods=100),'Value1': np.random.randn(100).cumsum(),'Value2': np.random.randn(100).cumsum(),'Category': np.random.choice(['A', 'B', 'C'], 100)})# 使用 Pandas 绘图fig, axes = plt.subplots(2, 2, figsize=(14, 10))# 折线图df.plot(x='Date', y=['Value1', 'Value2'], ax=axes[0, 0])axes[0, 0].set_title('折线图')axes[0, 0].set_xlabel('日期')# 柱状图df.groupby('Category').size().plot(kind='bar', ax=axes[0, 1], color='skyblue')axes[0, 1].set_title('类别计数')axes[0, 1].set_xlabel('类别')# 直方图df['Value1'].plot(kind='hist', bins=20, ax=axes[1, 0], edgecolor='black')axes[1, 0].set_title('值分布')# 箱线图df.boxplot(column=['Value1', 'Value2'], ax=axes[1, 1])axes[1, 1].set_title('箱线图')plt.tight_layout()plt.show()fig, ax = plt.subplots(figsize=(10, 6))ax.plot([1, 2, 3, 4], [1, 4, 9, 16])# 保存为不同格式plt.savefig('figure.png', dpi=300, bbox_inches='tight') # PNGplt.savefig('figure.pdf', bbox_inches='tight') # PDFplt.savefig('figure.svg', bbox_inches='tight') # SVGplt.savefig('figure.jpg', quality=95, bbox_inches='tight') # JPG# 透明背景plt.savefig('figure_transparent.png', transparent=True)# 指定尺寸plt.savefig('figure_custom.png', dpi=300, figsize=(10, 6))plt.show()# 交互式缩放和平移plt.ion() # 开启交互模式fig, ax = plt.subplots(figsize=(10, 6))x = np.linspace(0, 10, 100)line, = ax.plot(x, np.sin(x))# 更新数据for i inrange(5): line.set_ydata(np.sin(x + i)) plt.pause(0.5)plt.ioff() # 关闭交互模式plt.show()fig, ax = plt.subplots(figsize=(10, 6))ax.plot(x, y)ax.set_xlabel('时间 (天)', fontsize=12) # 清晰的轴标签ax.set_ylabel('销售额 (万元)', fontsize=12)ax.set_title('2024年上半年销售趋势', fontsize=14, fontweight='bold')# 使用配色方案from matplotlib import cmcolors = cm.viridis(np.linspace(0, 1, 5))# 或使用色盲友好的配色colors = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd']# 根据用途设置尺寸# 论文/报告: figsize=(6, 4) 或 (8, 6)# 演示文稿: figsize=(10, 6) 或 (12, 8)# 高分辨率保存: dpi=300# 推荐:面向对象fig, ax = plt.subplots(figsize=(10, 6))ax.plot(x, y)# 不推荐:pyplot 接口(复杂图表时)plt.figure(figsize=(10, 6))plt.plot(x, y)# 数据处理defprepare_data():return df.groupby('Category').agg({'Value': 'mean'})# 可视化defplot_bar(data): fig, ax = plt.subplots(figsize=(10, 6)) data.plot(kind='bar', ax=ax)return fig, axdata = prepare_data()fig, ax = plot_bar(data)