1.1 Matplotlib简介与安装

1.1.1 什么是Matplotlib

Matplotlib是Python中最流行的数据可视化库,由John D. Hunter于2003年创建。它提供了一个类似MATLAB的绘图接口,可以生成高质量的静态、动画和交互式可视化图表。

主要特点: - 功能强大且灵活 - 支持多种输出格式 - 高度可定制 - 与NumPy、Pandas等库无缝集成 - 活跃的社区支持

1.1.2 安装Matplotlib

# 使用pip安装
pip install matplotlib

# 使用conda安装
conda install matplotlib

# 安装完整的科学计算环境
pip install matplotlib numpy pandas jupyter

1.1.3 验证安装

import matplotlib
import matplotlib.pyplot as plt
import numpy as np

print(f"Matplotlib版本: {matplotlib.__version__}")

# 简单测试
x = np.linspace(0, 10, 100)
y = np.sin(x)

plt.figure(figsize=(8, 6))
plt.plot(x, y)
plt.title('Matplotlib安装测试')
plt.xlabel('X轴')
plt.ylabel('Y轴')
plt.grid(True)
plt.show()

1.2 基本绘图概念

1.2.1 Matplotlib架构

Matplotlib采用分层架构:

import matplotlib.pyplot as plt
import numpy as np

# 1. Backend Layer (后端层)
# 负责实际的图形渲染

# 2. Artist Layer (艺术家层)
# 所有图形元素都是Artist对象

# 3. Scripting Layer (脚本层)
# pyplot接口,最常用的层

class MatplotlibArchitecture:
    """Matplotlib架构演示"""
    
    def __init__(self):
        self.backend_info = {
            'Agg': '光栅图形',
            'SVG': '矢量图形',
            'PDF': 'PDF文档',
            'PS': 'PostScript',
            'Qt5Agg': 'Qt5交互式',
            'TkAgg': 'Tkinter交互式'
        }
    
    def show_backend_info(self):
        """显示后端信息"""
        import matplotlib
        print(f"当前后端: {matplotlib.get_backend()}")
        print("\n可用后端:")
        for backend, desc in self.backend_info.items():
            print(f"  {backend}: {desc}")
    
    def demonstrate_layers(self):
        """演示不同层的使用"""
        # Scripting Layer (pyplot)
        plt.figure(figsize=(12, 4))
        
        # 子图1: pyplot接口
        plt.subplot(1, 3, 1)
        x = np.linspace(0, 2*np.pi, 100)
        plt.plot(x, np.sin(x))
        plt.title('pyplot接口')
        
        # 子图2: 面向对象接口
        plt.subplot(1, 3, 2)
        fig, ax = plt.subplots()
        ax.plot(x, np.cos(x))
        ax.set_title('面向对象接口')
        
        # 子图3: Artist层
        plt.subplot(1, 3, 3)
        from matplotlib.patches import Circle
        fig, ax = plt.subplots()
        circle = Circle((0.5, 0.5), 0.3, color='red', alpha=0.5)
        ax.add_patch(circle)
        ax.set_xlim(0, 1)
        ax.set_ylim(0, 1)
        ax.set_title('Artist层')
        
        plt.tight_layout()
        plt.show()

# 使用示例
arch = MatplotlibArchitecture()
arch.show_backend_info()
arch.demonstrate_layers()

1.2.2 Figure和Axes

import matplotlib.pyplot as plt
import numpy as np

class FigureAxesDemo:
    """Figure和Axes概念演示"""
    
    def __init__(self):
        self.x = np.linspace(0, 10, 100)
        self.y1 = np.sin(self.x)
        self.y2 = np.cos(self.x)
    
    def basic_concepts(self):
        """基本概念演示"""
        # Figure: 整个图形窗口
        # Axes: 图形中的一个绘图区域
        
        # 方法1: pyplot接口
        plt.figure(figsize=(10, 6))
        plt.plot(self.x, self.y1, label='sin(x)')
        plt.plot(self.x, self.y2, label='cos(x)')
        plt.title('pyplot接口示例')
        plt.legend()
        plt.show()
        
        # 方法2: 面向对象接口
        fig, ax = plt.subplots(figsize=(10, 6))
        ax.plot(self.x, self.y1, label='sin(x)')
        ax.plot(self.x, self.y2, label='cos(x)')
        ax.set_title('面向对象接口示例')
        ax.legend()
        plt.show()
    
    def multiple_subplots(self):
        """多子图演示"""
        # 创建2x2的子图
        fig, axes = plt.subplots(2, 2, figsize=(12, 10))
        
        # 子图1: 线图
        axes[0, 0].plot(self.x, self.y1)
        axes[0, 0].set_title('线图')
        axes[0, 0].grid(True)
        
        # 子图2: 散点图
        axes[0, 1].scatter(self.x[::10], self.y1[::10])
        axes[0, 1].set_title('散点图')
        axes[0, 1].grid(True)
        
        # 子图3: 柱状图
        x_bar = np.arange(5)
        y_bar = np.random.rand(5)
        axes[1, 0].bar(x_bar, y_bar)
        axes[1, 0].set_title('柱状图')
        
        # 子图4: 饼图
        sizes = [25, 30, 20, 25]
        labels = ['A', 'B', 'C', 'D']
        axes[1, 1].pie(sizes, labels=labels, autopct='%1.1f%%')
        axes[1, 1].set_title('饼图')
        
        plt.tight_layout()
        plt.show()
    
    def subplot_layouts(self):
        """不同的子图布局"""
        # 使用GridSpec进行复杂布局
        from matplotlib.gridspec import GridSpec
        
        fig = plt.figure(figsize=(12, 8))
        gs = GridSpec(3, 3, figure=fig)
        
        # 大图占据左上角2x2
        ax1 = fig.add_subplot(gs[0:2, 0:2])
        ax1.plot(self.x, self.y1)
        ax1.set_title('主图')
        
        # 右上角小图
        ax2 = fig.add_subplot(gs[0, 2])
        ax2.plot(self.x, self.y2)
        ax2.set_title('小图1')
        
        # 右中间小图
        ax3 = fig.add_subplot(gs[1, 2])
        ax3.scatter(self.x[::20], self.y1[::20])
        ax3.set_title('小图2')
        
        # 底部横跨整个宽度
        ax4 = fig.add_subplot(gs[2, :])
        ax4.plot(self.x, self.y1 + self.y2)
        ax4.set_title('底部图')
        
        plt.tight_layout()
        plt.show()

# 使用示例
demo = FigureAxesDemo()
demo.basic_concepts()
demo.multiple_subplots()
demo.subplot_layouts()

1.3 图形对象模型

1.3.1 Artist对象层次结构

import matplotlib.pyplot as plt
import matplotlib.patches as patches
import numpy as np

class ArtistDemo:
    """Artist对象演示"""
    
    def __init__(self):
        self.fig = None
        self.ax = None
    
    def artist_hierarchy(self):
        """Artist层次结构演示"""
        self.fig, self.ax = plt.subplots(figsize=(10, 8))
        
        # Primitive Artists (基本艺术家)
        # Line2D
        x = np.linspace(0, 10, 100)
        line, = self.ax.plot(x, np.sin(x), 'b-', linewidth=2, label='sin(x)')
        
        # Text
        text = self.ax.text(5, 0.5, 'Hello Matplotlib!', 
                           fontsize=14, color='red',
                           bbox=dict(boxstyle='round', facecolor='yellow'))
        
        # Patch (Rectangle)
        rect = patches.Rectangle((2, -0.5), 2, 1, 
                               linewidth=2, edgecolor='green', 
                               facecolor='lightgreen', alpha=0.5)
        self.ax.add_patch(rect)
        
        # Patch (Circle)
        circle = patches.Circle((7, 0.5), 0.5, 
                              linewidth=2, edgecolor='purple', 
                              facecolor='lavender', alpha=0.7)
        self.ax.add_patch(circle)
        
        # Collection (scatter)
        x_scatter = np.random.rand(50) * 10
        y_scatter = np.random.rand(50) * 2 - 1
        scatter = self.ax.scatter(x_scatter, y_scatter, 
                                c=np.random.rand(50), 
                                s=100, alpha=0.6)
        
        # Composite Artists (复合艺术家)
        self.ax.set_title('Artist对象层次结构演示', fontsize=16)
        self.ax.set_xlabel('X轴', fontsize=12)
        self.ax.set_ylabel('Y轴', fontsize=12)
        self.ax.legend()
        self.ax.grid(True, alpha=0.3)
        
        plt.show()
        
        # 打印Artist信息
        self.print_artist_info()
    
    def print_artist_info(self):
        """打印Artist对象信息"""
        print("Figure的子Artist:")
        for i, child in enumerate(self.fig.get_children()):
            print(f"  {i}: {type(child).__name__}")
        
        print("\nAxes的子Artist:")
        for i, child in enumerate(self.ax.get_children()):
            print(f"  {i}: {type(child).__name__}")
    
    def custom_artist(self):
        """自定义Artist"""
        from matplotlib.artist import Artist
        from matplotlib.patches import Polygon
        
        class CustomArtist(Artist):
            def __init__(self, ax):
                super().__init__()
                self.ax = ax
            
            def draw(self, renderer):
                # 绘制自定义图形
                vertices = np.array([[0.2, 0.2], [0.8, 0.2], 
                                   [0.5, 0.8], [0.2, 0.2]])
                triangle = Polygon(vertices, closed=True, 
                                 facecolor='orange', alpha=0.7)
                self.ax.add_patch(triangle)
        
        fig, ax = plt.subplots(figsize=(8, 6))
        
        # 添加自定义Artist
        custom = CustomArtist(ax)
        ax.add_artist(custom)
        
        ax.set_xlim(0, 1)
        ax.set_ylim(0, 1)
        ax.set_title('自定义Artist示例')
        
        plt.show()

# 使用示例
artist_demo = ArtistDemo()
artist_demo.artist_hierarchy()
artist_demo.custom_artist()

1.3.2 属性设置与获取

import matplotlib.pyplot as plt
import numpy as np

class PropertyDemo:
    """属性设置演示"""
    
    def __init__(self):
        self.x = np.linspace(0, 10, 100)
        self.y = np.sin(self.x)
    
    def property_methods(self):
        """属性设置方法演示"""
        fig, axes = plt.subplots(2, 2, figsize=(12, 10))
        
        # 方法1: 创建时设置
        axes[0, 0].plot(self.x, self.y, color='red', linewidth=3, 
                       linestyle='--', marker='o', markersize=5)
        axes[0, 0].set_title('创建时设置属性')
        
        # 方法2: 使用set_*方法
        line, = axes[0, 1].plot(self.x, self.y)
        line.set_color('blue')
        line.set_linewidth(2)
        line.set_linestyle('-.')
        line.set_marker('s')
        line.set_markersize(4)
        axes[0, 1].set_title('使用set_*方法')
        
        # 方法3: 使用setp函数
        line, = axes[1, 0].plot(self.x, self.y)
        plt.setp(line, color='green', linewidth=2.5, 
                linestyle=':', marker='^', markersize=6)
        axes[1, 0].set_title('使用setp函数')
        
        # 方法4: 使用update方法
        line, = axes[1, 1].plot(self.x, self.y)
        line.update({'color': 'purple', 'linewidth': 2, 
                    'linestyle': '-', 'marker': 'D', 'markersize': 5})
        axes[1, 1].set_title('使用update方法')
        
        plt.tight_layout()
        plt.show()
    
    def get_properties(self):
        """获取属性演示"""
        fig, ax = plt.subplots(figsize=(8, 6))
        line, = ax.plot(self.x, self.y, 'ro-')
        
        # 获取属性
        print("Line2D属性:")
        print(f"颜色: {line.get_color()}")
        print(f"线宽: {line.get_linewidth()}")
        print(f"线型: {line.get_linestyle()}")
        print(f"标记: {line.get_marker()}")
        print(f"标记大小: {line.get_markersize()}")
        
        # 获取所有属性
        print("\n所有可设置的属性:")
        for prop in line.properties():
            print(f"  {prop}")
        
        # 使用getp函数
        print(f"\n使用getp获取颜色: {plt.getp(line, 'color')}")
        
        plt.show()
    
    def property_animation(self):
        """属性动画演示"""
        import matplotlib.animation as animation
        
        fig, ax = plt.subplots(figsize=(8, 6))
        line, = ax.plot(self.x, self.y, 'b-')
        ax.set_xlim(0, 10)
        ax.set_ylim(-1.5, 1.5)
        ax.set_title('属性动画演示')
        
        def animate(frame):
            # 改变线条颜色和透明度
            alpha = 0.3 + 0.7 * (np.sin(frame * 0.1) + 1) / 2
            color = plt.cm.viridis(frame / 100)
            line.set_alpha(alpha)
            line.set_color(color)
            
            # 改变数据
            y_new = np.sin(self.x + frame * 0.1)
            line.set_ydata(y_new)
            
            return line,
        
        anim = animation.FuncAnimation(fig, animate, frames=200, 
                                     interval=50, blit=True, repeat=True)
        plt.show()
        
        return anim

# 使用示例
prop_demo = PropertyDemo()
prop_demo.property_methods()
prop_demo.get_properties()
# anim = prop_demo.property_animation()  # 取消注释以运行动画

1.4 第一个图表

1.4.1 简单线图

import matplotlib.pyplot as plt
import numpy as np

class FirstPlotDemo:
    """第一个图表演示"""
    
    def __init__(self):
        # 设置中文字体
        plt.rcParams['font.sans-serif'] = ['SimHei', 'Arial Unicode MS']
        plt.rcParams['axes.unicode_minus'] = False
    
    def simple_line_plot(self):
        """简单线图"""
        # 生成数据
        x = np.linspace(0, 2*np.pi, 100)
        y = np.sin(x)
        
        # 创建图表
        plt.figure(figsize=(10, 6))
        plt.plot(x, y)
        
        # 添加标题和标签
        plt.title('我的第一个Matplotlib图表', fontsize=16)
        plt.xlabel('X轴 (弧度)', fontsize=12)
        plt.ylabel('Y轴 (sin值)', fontsize=12)
        
        # 添加网格
        plt.grid(True, alpha=0.3)
        
        # 显示图表
        plt.show()
    
    def enhanced_line_plot(self):
        """增强版线图"""
        # 生成数据
        x = np.linspace(0, 4*np.pi, 200)
        y1 = np.sin(x)
        y2 = np.cos(x)
        y3 = np.sin(x) * np.cos(x)
        
        # 创建图表
        plt.figure(figsize=(12, 8))
        
        # 绘制多条线
        plt.plot(x, y1, 'b-', linewidth=2, label='sin(x)')
        plt.plot(x, y2, 'r--', linewidth=2, label='cos(x)')
        plt.plot(x, y3, 'g:', linewidth=3, label='sin(x)cos(x)')
        
        # 美化图表
        plt.title('三角函数对比', fontsize=18, fontweight='bold')
        plt.xlabel('X轴 (弧度)', fontsize=14)
        plt.ylabel('Y轴 (函数值)', fontsize=14)
        
        # 设置坐标轴范围
        plt.xlim(0, 4*np.pi)
        plt.ylim(-1.2, 1.2)
        
        # 添加图例
        plt.legend(fontsize=12, loc='upper right')
        
        # 添加网格
        plt.grid(True, alpha=0.3, linestyle='-', linewidth=0.5)
        
        # 添加注释
        plt.annotate('最大值', xy=(np.pi/2, 1), xytext=(np.pi/2, 1.3),
                    arrowprops=dict(arrowstyle='->', color='red'),
                    fontsize=12, ha='center')
        
        # 调整布局
        plt.tight_layout()
        
        # 显示图表
        plt.show()
    
    def multiple_plots(self):
        """多个子图"""
        # 生成数据
        x = np.linspace(0, 10, 100)
        
        # 创建子图
        fig, axes = plt.subplots(2, 2, figsize=(12, 10))
        fig.suptitle('多种图表类型展示', fontsize=16, fontweight='bold')
        
        # 子图1: 线图
        axes[0, 0].plot(x, np.sin(x), 'b-', linewidth=2)
        axes[0, 0].set_title('线图')
        axes[0, 0].set_xlabel('X')
        axes[0, 0].set_ylabel('sin(X)')
        axes[0, 0].grid(True, alpha=0.3)
        
        # 子图2: 散点图
        y_scatter = np.sin(x) + np.random.normal(0, 0.1, len(x))
        axes[0, 1].scatter(x, y_scatter, alpha=0.6, s=30)
        axes[0, 1].set_title('散点图')
        axes[0, 1].set_xlabel('X')
        axes[0, 1].set_ylabel('sin(X) + 噪声')
        axes[0, 1].grid(True, alpha=0.3)
        
        # 子图3: 柱状图
        x_bar = np.arange(1, 6)
        y_bar = np.random.rand(5) * 10
        axes[1, 0].bar(x_bar, y_bar, color=['red', 'green', 'blue', 'orange', 'purple'])
        axes[1, 0].set_title('柱状图')
        axes[1, 0].set_xlabel('类别')
        axes[1, 0].set_ylabel('数值')
        
        # 子图4: 直方图
        data = np.random.normal(0, 1, 1000)
        axes[1, 1].hist(data, bins=30, alpha=0.7, color='skyblue', edgecolor='black')
        axes[1, 1].set_title('直方图')
        axes[1, 1].set_xlabel('数值')
        axes[1, 1].set_ylabel('频次')
        
        # 调整子图间距
        plt.tight_layout()
        
        # 显示图表
        plt.show()
    
    def save_plot(self):
        """保存图表"""
        # 生成数据
        x = np.linspace(0, 2*np.pi, 100)
        y = np.sin(x)
        
        # 创建图表
        plt.figure(figsize=(10, 6))
        plt.plot(x, y, 'b-', linewidth=2)
        plt.title('保存图表示例')
        plt.xlabel('X轴')
        plt.ylabel('Y轴')
        plt.grid(True, alpha=0.3)
        
        # 保存为不同格式
        plt.savefig('my_first_plot.png', dpi=300, bbox_inches='tight')
        plt.savefig('my_first_plot.pdf', bbox_inches='tight')
        plt.savefig('my_first_plot.svg', bbox_inches='tight')
        
        print("图表已保存为:")
        print("- my_first_plot.png (高分辨率PNG)")
        print("- my_first_plot.pdf (PDF矢量图)")
        print("- my_first_plot.svg (SVG矢量图)")
        
        plt.show()

# 使用示例
first_plot = FirstPlotDemo()
first_plot.simple_line_plot()
first_plot.enhanced_line_plot()
first_plot.multiple_plots()
first_plot.save_plot()

1.5 常用配置选项

1.5.1 全局配置

import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np

class ConfigurationDemo:
    """配置选项演示"""
    
    def __init__(self):
        self.x = np.linspace(0, 10, 100)
        self.y = np.sin(self.x)
    
    def rcparams_demo(self):
        """rcParams配置演示"""
        # 查看当前配置
        print("当前图形大小:", plt.rcParams['figure.figsize'])
        print("当前字体大小:", plt.rcParams['font.size'])
        print("当前线宽:", plt.rcParams['lines.linewidth'])
        
        # 保存原始配置
        original_params = plt.rcParams.copy()
        
        # 修改全局配置
        plt.rcParams.update({
            'figure.figsize': [12, 8],
            'font.size': 14,
            'lines.linewidth': 2.5,
            'lines.markersize': 8,
            'axes.grid': True,
            'grid.alpha': 0.3,
            'axes.spines.top': False,
            'axes.spines.right': False,
            'font.sans-serif': ['SimHei', 'Arial Unicode MS'],
            'axes.unicode_minus': False
        })
        
        # 创建图表
        plt.figure()
        plt.plot(self.x, self.y, 'o-', label='sin(x)')
        plt.plot(self.x, np.cos(self.x), 's-', label='cos(x)')
        plt.title('使用全局配置的图表')
        plt.xlabel('X轴')
        plt.ylabel('Y轴')
        plt.legend()
        plt.show()
        
        # 恢复原始配置
        plt.rcParams.update(original_params)
    
    def style_sheets(self):
        """样式表演示"""
        # 查看可用样式
        print("可用样式:")
        for style in plt.style.available:
            print(f"  {style}")
        
        # 使用不同样式
        styles = ['default', 'seaborn-v0_8', 'ggplot', 'bmh']
        
        fig, axes = plt.subplots(2, 2, figsize=(15, 12))
        axes = axes.flatten()
        
        for i, style in enumerate(styles):
            with plt.style.context(style):
                axes[i].plot(self.x, self.y, 'o-', label='sin(x)')
                axes[i].plot(self.x, np.cos(self.x), 's-', label='cos(x)')
                axes[i].set_title(f'样式: {style}')
                axes[i].set_xlabel('X轴')
                axes[i].set_ylabel('Y轴')
                axes[i].legend()
                axes[i].grid(True)
        
        plt.tight_layout()
        plt.show()
    
    def custom_style(self):
        """自定义样式"""
        # 创建自定义样式字典
        custom_style = {
            'figure.figsize': [10, 6],
            'axes.facecolor': '#f8f9fa',
            'axes.edgecolor': '#dee2e6',
            'axes.linewidth': 1.2,
            'axes.grid': True,
            'grid.color': '#e9ecef',
            'grid.linestyle': '-',
            'grid.linewidth': 0.8,
            'grid.alpha': 0.8,
            'lines.linewidth': 2.5,
            'lines.markersize': 8,
            'font.size': 12,
            'axes.titlesize': 16,
            'axes.labelsize': 14,
            'xtick.labelsize': 12,
            'ytick.labelsize': 12,
            'legend.fontsize': 12,
            'axes.spines.top': False,
            'axes.spines.right': False,
            'axes.spines.left': True,
            'axes.spines.bottom': True
        }
        
        # 应用自定义样式
        with plt.rc_context(custom_style):
            plt.figure()
            plt.plot(self.x, self.y, 'o-', color='#007bff', label='sin(x)')
            plt.plot(self.x, np.cos(self.x), 's-', color='#28a745', label='cos(x)')
            plt.title('自定义样式图表')
            plt.xlabel('X轴')
            plt.ylabel('Y轴')
            plt.legend()
            plt.show()
    
    def color_configuration(self):
        """颜色配置演示"""
        # 颜色循环
        colors = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', 
                 '#9467bd', '#8c564b', '#e377c2', '#7f7f7f']
        
        plt.rcParams['axes.prop_cycle'] = plt.cycler(color=colors)
        
        fig, axes = plt.subplots(1, 2, figsize=(15, 6))
        
        # 子图1: 默认颜色循环
        for i in range(8):
            y = np.sin(self.x + i * np.pi/4)
            axes[0].plot(self.x, y, linewidth=2, label=f'线条{i+1}')
        
        axes[0].set_title('自定义颜色循环')
        axes[0].legend()
        axes[0].grid(True, alpha=0.3)
        
        # 子图2: 颜色映射
        y_data = [np.sin(self.x + i * np.pi/8) for i in range(5)]
        colors_map = plt.cm.viridis(np.linspace(0, 1, 5))
        
        for i, (y, color) in enumerate(zip(y_data, colors_map)):
            axes[1].plot(self.x, y, color=color, linewidth=2, label=f'线条{i+1}')
        
        axes[1].set_title('使用颜色映射')
        axes[1].legend()
        axes[1].grid(True, alpha=0.3)
        
        plt.tight_layout()
        plt.show()
    
    def backend_configuration(self):
        """后端配置演示"""
        import matplotlib
        
        print(f"当前后端: {matplotlib.get_backend()}")
        print(f"交互式模式: {matplotlib.is_interactive()}")
        
        # 后端信息
        backend_info = {
            'Agg': '非交互式,适合服务器环境',
            'Qt5Agg': '交互式,基于Qt5',
            'TkAgg': '交互式,基于Tkinter',
            'notebook': 'Jupyter Notebook内联显示'
        }
        
        print("\n常用后端:")
        for backend, desc in backend_info.items():
            print(f"  {backend}: {desc}")
        
        # 设置后端示例(注意:需要在导入pyplot之前设置)
        print("\n设置后端示例:")
        print("import matplotlib")
        print("matplotlib.use('Agg')  # 设置为Agg后端")
        print("import matplotlib.pyplot as plt")

# 使用示例
config_demo = ConfigurationDemo()
config_demo.rcparams_demo()
config_demo.style_sheets()
config_demo.custom_style()
config_demo.color_configuration()
config_demo.backend_configuration()

1.6 本章总结

1.6.1 学习要点回顾

  1. Matplotlib基础概念

    • 分层架构:Backend、Artist、Scripting
    • Figure和Axes的关系
    • Artist对象模型
  2. 绘图接口

    • pyplot接口(类MATLAB)
    • 面向对象接口(推荐)
    • Artist层接口(高级定制)
  3. 基本绘图流程

    • 创建Figure和Axes
    • 绘制图形元素
    • 设置属性和样式
    • 显示或保存图表
  4. 配置管理

    • rcParams全局配置
    • 样式表系统
    • 自定义样式
    • 后端选择

1.6.2 实践练习

# 练习1: 创建一个包含多个子图的复合图表
def practice_1():
    """练习:多子图复合图表"""
    # TODO: 创建2x3的子图布局
    # 包含:线图、散点图、柱状图、直方图、饼图、箱线图
    pass

# 练习2: 自定义样式主题
def practice_2():
    """练习:创建自定义样式主题"""
    # TODO: 设计一个专业的图表样式
    # 包含:颜色方案、字体设置、网格样式等
    pass

# 练习3: 属性动态修改
def practice_3():
    """练习:动态修改图表属性"""
    # TODO: 创建一个图表,然后动态修改其属性
    # 如:颜色、线型、标记等
    pass

1.6.3 常见问题

Q: pyplot和面向对象接口有什么区别? A: pyplot接口简单易用,适合快速绘图;面向对象接口更灵活,适合复杂图表和程序化绘图。

Q: 如何选择合适的后端? A: 交互式环境选择Qt5Agg或TkAgg;服务器环境选择Agg;Jupyter Notebook使用inline或notebook。

Q: 中文显示乱码怎么解决? A: 设置中文字体:plt.rcParams['font.sans-serif'] = ['SimHei']

Q: 如何提高图表质量? A: 使用高DPI、矢量格式、合适的颜色方案和字体大小。

1.6.4 下章预告

下一章我们将学习各种基础图表类型,包括线图、散点图、柱状图等的详细用法和最佳实践。