python科研绘图教程 1| 恭喜宿主获得了matplotlib的炼气期功法

文摘   2024-10-11 11:35   新加坡  
点击订阅公众号 | 前沿学术成果每日更新               

文章目录

  • Matplotlib库简介

  • Matplotlib库中绘图对象概述

  • matplotlib的绘图实战

    • 热图

    • 箱体图

    • 动态图表展示

Matplotlib库简介

Matplotlib 是 Python 的一个绘图库,它可用于各种平台,提供多种输出格式,并且能够生成发布质量级别的图形。作为一个绘图工具,它让用户可以在脚本、Python 和 IPython shell 乃至 Jupyter notebook 中创建图形。Matplotlib 最初由 John D. Hunter 在2003年创建,目的是为Python创建一个健壮、易用和功能强大的绘图工具。如今,Matplotlib 已经发展成为 Python 最受欢迎的数据可视化库之一,尤其在科学计算和数据分析领域中被广泛应用。

官方网址:https://matplotlib.org/

Matplotlib的主要优势在于:

  1. 多样的绘图功能:Matplotlib 支持数十种图表类型——从条形图和线图到热图和散点图。它可以用于绘制复杂的图表如误差线图、直方图、箱形图和密度图等,使得数据以图形的形式被更直观地展示。每种图表都可以高度自定义,包括调整颜色、网格线、图层等多种属性。

  2. 精确的绘图元素控制能力:Matplotlib的强大之处不仅体现在其广泛的绘图类型和集成能力上,还特别在于它提供了精细控制绘图元素的能力。这一点对于科学研究和精确数据可视化尤为重要,因为它允许研究人员和分析师以精确和定制的方式呈现数据,确保可视化结果既精准又信息丰富

  3. 高度的可定制性:Matplotlib 提供了庞大的API集合,用户可以调整几乎所有元素的视觉属性,从轴的位置到字体的大小和颜色。这种灵活性尤其适合于需要精细控制图形外观的科学报告和论文。

  4. 强大的集成能力:与 Pandas 和 NumPy 等数据处理库无缝集成是 Matplotlib 的另一个重要优势。这意味着用户可以轻松地将数据框架直接转换为图表,并利用 NumPy 的数学能力来处理复杂的计算,然后用 Matplotlib 进行可视化,这使得从数据处理到最终的图形展示形成一个连贯的工作流

  5. 跨平台和多输出格式:Matplotlib 可以在 Windows、MacOS 和 Linux 等多种操作系统上运行。除此之外,Matplotlib 支持多种输出格式,包括 PNG、PDF、SVG、EPS,TIFF以及高清的交互式图形格式。这使得Matplotlib非常适合需要在不同媒介上发布图形的用户。

    这一点对于科研绘图非常重要,论文投稿常常对于DPI以及图片格式有诸多要求

Matplotlib库中绘图对象概述

Matplotlib库中定义了很多绘图对象,如下图所示。该图解释了如何使用 matplotlib 库在 Python 中创建和标注图形的各个组成部分,非常适合初学者理解和学习如何在 Python 中使用 matplotlib 来创建、控制和标注复杂的图表。

../../_images/anatomy.png

关于matplotlib各个绘图元素的简介

  1. Figure(图形)

  • 功能:表示整个图像窗口或绘图区域,在 matplotlib 中是最顶层的容器,可以包含多个 Axes 对象。
  • 使用方式:通过调用 plt.figure() 创建一个新的 Figure 对象。
  • Axes(坐标轴)

    • 功能:图形中的一个单独的绘图区域,可以绘制数据、设置图表标签和标题。
    • 使用方式:使用 fig.subplots()plt.subplots() 创建一个或多个坐标轴。
  • Title(标题)

    • 功能:提供图表的主标题,帮助观众理解图表的主要内容。
    • 使用方式:通过 ax.set_title("标题内容") 来设置坐标轴的标题。
  • Legend(图例)

    • 功能:解释图中使用的各种数据标记和颜色代表什么,增加图表的可读性。
    • 使用方式:通过 ax.legend() 添加图例,通常需要在绘图函数中使用 label 参数标记不同的数据系列。
  • Grid(网格线)

    • 功能:在图表背景添加网格线,便于观察数据点的精确位置。
    • 使用方式:通过 ax.grid(True) 开启,可调整样式和颜色等属性。
  • Line(线条)

    • 功能:连接数据点,显示数据点之间的关系或趋势。
    • 使用方式:使用 ax.plot(x, y) 绘制线条,其中 xy 是数据点的坐标列表。
  • Markers(标记)

    • 功能:以图形标记(如圆形、方形等)直观显示每个数据点的位置。
    • 使用方式:通过 ax.scatter(x, y) 绘制散点图,可以自定义标记的形状、大小和颜色。
  • Spine(轴脊)

    • 功能:图表的四边框,可以被设置为不可见,或者改变位置,用以美化图表。
    • 使用方式:通过 ax.spines['位置'].set_visible(False) 控制显示或隐藏。
  • x Axis Label(x轴标签)

    • 功能:x轴的说明文字,通常显示与 x 轴数据相关的信息。
    • 使用方式:通过 ax.set_xlabel("标签内容") 设置 x 轴的标签。
  • y Axis Label(y轴标签)

    • 功能:y轴的说明文字,通常显示与 y 轴数据相关的信息。
    • 使用方式:通过 ax.set_ylabel("标签内容") 设置 y 轴的标签。
  • Major Tick(主刻度)

    • 功能:在坐标轴上的主要的度量点,通常更粗或更显著。
    • 使用方式:通过 ax.xaxis.set_major_locator(plt.MaxNLocator(5)) 设置 x 轴的主刻度,参数决定刻度的数量。
  • Minor Tick(次刻度)

    • 功能:在坐标轴上标示次要的度量点,通常比主刻度小,用于提供更精细的度量刻度。
    • 使用方式:通过 ax.xaxis.set_minor_locator(AutoMinorLocator()) 设置次刻度的位置。
  • Major Tick Label(主刻度标签)

    • 功能:显示与主刻度线对应的数值或标签。
    • 使用方式:通过 ax.xaxis.set_major_formatter(FormatStrFormatter('%0.1f')) 设置主刻度的格式化输出。

    下面的两张速查表总结了matplotlib中的操作,对于快速了解matplotlib的各项特性非常有帮助,建议保存:

    img
    img

    matplotlib的绘图实战

    热图

    热图是一种通过颜色变化来表示数据大小的有效图表形式,非常适合表现二维数组中的数据关系。下面例子中,通过使用matplotlib绘制热图,清楚地展示每个农民对应每种蔬菜的收获量,并通过颜色的变化直观感受到数据的大小差异。

    每行代码后都有注释解释,以帮助初学者快速理解

    import numpy as np                  # 导入numpy库,用于数据操作
    import matplotlib                  # 导入matplotlib库
    import matplotlib.pyplot as plt    # 导入matplotlib的pyplot模块,用于绘图

    # 定义蔬菜名称列表
    vegetables = ["cucumber""tomato""lettuce""asparagus""potato""wheat""barley"]
    # 定义农民名称列表
    farmers = ["Farmer Joe""Upland Bros.""Smith Gardening""Agrifun""Organiculture""BioGoods Ltd.""Cornylee Corp."]

    # 定义一个数组,表示不同农民种植不同蔬菜的收获量(单位:吨/年)
    harvest = np.array([
        [0.82.42.53.90.04.00.0],
        [2.40.04.01.02.70.00.0],
        [1.12.40.84.31.94.40.0],
        [0.60.00.30.03.10.00.0],
        [0.71.70.62.62.26.20.0],
        [1.31.20.00.00.03.25.1],
        [0.12.00.01.40.01.96.3]
    ])

    fig, ax = plt.subplots()           # 创建一个图形和一个坐标轴
    im = ax.imshow(harvest)            # 使用imshow绘制热图,传入收获数据

    # 设置x轴刻度位置和标签
    ax.set_xticks(np.arange(len(farmers)), labels=farmers)
    # 设置y轴刻度位置和标签
    ax.set_yticks(np.arange(len(vegetables)), labels=vegetables)

    # 设置x轴标签的旋转角度和对齐方式
    plt.setp(ax.get_xticklabels(), rotation=45, ha="right", rotation_mode="anchor")

    # 遍历数据维度,为每个数据点添加文本注解
    for i in range(len(vegetables)):
        for j in range(len(farmers)):
            text = ax.text(j, i, harvest[i, j], ha="center", va="center", color="w")

    ax.set_title("Harvest of local farmers (in tons/year)")  # 设置图表标题
    fig.tight_layout()    # 调整布局,确保元素不重叠
    plt.show()            # 显示图表
    Harvest of local farmers (in tons/year)

    这个例子实现热图的逻辑步骤如下

    1. 数据定义:首先定义涉及的数据,包括农民和蔬菜的名称以及他们的收获量数据。
    2. 热图绘制:使用 imshow() 函数将收获量数据转换为热图,不同的收获量将通过颜色的深浅来表示。
    3. 标签设置:设置图表的 x 轴和 y 轴标签,显示具体的农民和蔬菜名称。
    4. 标签旋转:为了更好地显示,将 x 轴的标签旋转45度以避免重叠。
    5. 数据注释:在热图的每一个单元格中添加数据注释,即每种蔬菜的具体收获量。
    6. 布局调整:调整布局,确保图表的标题、标签等不会重叠。
    7. 显示图表:最后,使用 plt.show() 显示最终的图表。

    箱体图

    下面代码用于生成包含两种风格的箱型图(Boxplot),一个是标准的矩形箱型图,另一个是带缺口的箱型图。每个箱型图表示了三组不同标准差的正态分布数据。

    import matplotlib.pyplot as plt  # 导入matplotlib.pyplot用于绘图
    import numpy as np  # 导入numpy库用于数学运算

    # 设置随机数种子,确保每次运行生成的随机数相同
    np.random.seed(19680801)
    # 生成三组不同标准差的正态分布数据
    all_data = [np.random.normal(0, std, size=100for std in range(14)]
    # 为每组数据设置标签
    labels = ['x1''x2''x3']

    # 创建一个图形和两个子图,尺寸为9x4英寸
    fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(94))

    # 在第一个子图上绘制矩形箱型图
    bplot1 = ax1.boxplot(all_data,
                         vert=True,  # 设置箱型图为垂直方向
                         patch_artist=True,  # 启用色块填充
                         labels=labels)  # 使用labels为x轴刻度添加标签
    ax1.set_title('Rectangular box plot')  # 设置子图标题

    # 在第二个子图上绘制带缺口的箱型图
    bplot2 = ax2.boxplot(all_data,
                         notch=True,  # 设置箱体中间带有缺口
                         vert=True,  # 设置箱型图为垂直方向
                         patch_artist=True,  # 启用色块填充
                         labels=labels)  # 使用labels为x轴刻度添加标签
    ax2.set_title('Notched box plot')  # 设置子图标题

    # 为两种箱型图设置填充颜色
    colors = ['pink''lightblue''lightgreen']
    for bplot in (bplot1, bplot2):
        for patch, color in zip(bplot['boxes'], colors):
            patch.set_facecolor(color)  # 设置箱体的颜色

    # 为两个子图添加水平网格线,设置x和y轴的标签
    for ax in [ax1, ax2]:
        ax.yaxis.grid(True)  # 开启y轴的网格线
        ax.set_xlabel('Three separate samples')  # 设置x轴标签
        ax.set_ylabel('Observed values')  # 设置y轴标签

    plt.show()  # 显示图表

    image-20241010234654195

    这个例子实现箱体的逻辑步骤是:

    1. 数据准备:首先,通过 np.random.normal 生成三组服从正态分布的随机数据,每组数据有100个点,且标准差逐渐增大。
    2. 绘图设置:使用 plt.subplots 创建一个包含两个子图的画布,大小为9x4英寸。
    3. 绘制箱型图:使用 ax1.boxplotax2.boxplot 分别在两个子图上绘制标准箱型图和带缺口的箱型图。
    4. 美化:通过 patch_artist=True 参数使箱型图填充颜色,并为每个箱体设置不同的颜色。
    5. 标签与标题:给每个子图设置标题,并为箱型图的每个部分设置对应的样本标签。
    6. 添加网格线与标签:在每个子图上添加水平网格线,设置适当的x轴和y轴标签,增强图表的可读性。
    7. 显示结果:最后使用 plt.show() 显示整个图形。

    动态图表展示

    下面的代码通过matplotlib的动态绘图功能展示了分形图形--koch雪花的生成过程。

    分形是一种在不同尺度上都表现出自相似性的几何形状或数学集合。这个概念由法国数学家伯努瓦·曼德勃罗(Benoit Mandelbrot)在20世纪70年代提出,他也是“分形”这个词的创造者。分形具有以下几个关键特征:

    自相似性:分形在其结构中展现出某种形式的自相似性。这意味着当你放大分形的一部分时,你会看到与整体类似的图案。这种自相似性可以是严格的(完全相同),也可以是统计上的(大致相同)。无限细节:分形通常包含无限的细节,无论你放大多少倍,总能看到新的结构和细节。这种特性使得分形在数学上非常有趣,也使其在自然界中的许多现象中得以体现。分数维度:分形的维度通常是分数,而不是整数。例如,一个线段是一维的,一个平面是二维的,而一个立方体是三维的。但是分形的维度可能是一个介于这些整数之间的值,比如1.26或2.53等。递归定义:分形可以通过简单的递归规则生成。这些规则不断重复应用,从而产生复杂的结构。经典的例子包括科赫雪花、谢尔宾斯基三角形和曼德勃罗集。

    import numpy as np                   # 导入 numpy 库用于数学运算
    import matplotlib.pyplot as plt      # 导入 matplotlib.pyplot 用于绘图
    from matplotlib.animation import FuncAnimation  # 导入 FuncAnimation 用于创建动画

    # 定义科赫雪花函数,order 为阶数,scale 为缩放比例
    def koch_snowflake(order, scale=10):
        # 定义一个内部函数,递归生成科赫雪花的顶点
        def _koch_snowflake_complex(order):
            if order == 0:  # 如果是 0 阶,返回一个等边三角形的顶点
                angles = np.array([0120240]) + 90  # 三角形的角度
                return scale / np.sqrt(3) * np.exp(np.deg2rad(angles) * 1j)  # 通过复数来计算顶点坐标
            else:
                ZR = 0.5 - 0.5j * np.sqrt(3) / 3  # 复数,用于计算中点偏移
                p1 = _koch_snowflake_complex(order - 1)  # 递归生成上一阶的顶点
                p2 = np.roll(p1, shift=-1)  # 将顶点数组循环移位
                dp = p2 - p1  # 计算相邻顶点的差
                new_points = np.empty(len(p1) * 4, dtype=np.complex128)  # 创建新的顶点数组
                new_points[::4] = p1
                new_points[1::4] = p1 + dp / 3
                new_points[2::4] = p1 + dp * ZR  # 计算中间折点
                new_points[3::4] = p1 + dp / 3 * 2
                return new_points
        points = _koch_snowflake_complex(order)  # 生成科赫雪花的顶点
        x, y = points.real, points.imag  # 将复数坐标分解为实部和虚部,对应 x, y 坐标
        return x, y

    fig, ax = plt.subplots()  # 创建图形和坐标轴
    ax.axis('equal')  # 设置坐标轴的比例相同

    # 定义动画的更新函数
    def update(frame):
        ax.clear()  # 清除当前坐标轴内容
        ax.axis('off')  # 关闭坐标轴
        x, y = koch_snowflake(order=frame)  # 生成对应阶数的科赫雪花
        ax.fill(x, y)  # 填充科赫雪花区域

    ani = FuncAnimation(fig, update, frames=np.arange(06), repeat=True)  # 创建动画,帧数为0到5阶
    plt.show()  # 显示动画

    kn

    下面是实现科赫雪花动画的详细逻辑解释:

    1. 科赫雪花计算函数
    • koch_snowflake(order, scale=10) 是主函数,接收阶数 order 和缩放因子 scale
    • 内嵌函数 _koch_snowflake_complex(order) 用递归的方式计算科赫雪花的顶点。当阶数 order 为0时,返回一个简单的等边三角形的顶点。对于高阶科赫雪花,函数将每条边细分成4部分,添加新的点以形成特定的锯齿形状,递归继续这一过程直到达到所需的阶数。
  • 绘图和动画设置
    • 使用 plt.subplots() 创建图形 (fig) 和坐标轴 (ax)。
    • ax.axis('equal') 确保 x 轴和 y 轴具有相同的比例,使得雪花的显示是均匀的。
    • ax.axis('off') 关闭坐标轴的显示,以便更清晰地展示雪花的形状。
  • 动画更新函数
    • update(frame) 函数作为动画的核心,每一帧调用一次。frame 参数代表当前的动画帧(也对应科赫雪花的阶数)。
    • 每次调用 update 时,先通过 ax.clear() 清除之前的图形,然后调用 koch_snowflake 生成当前阶数的雪花坐标,使用 ax.fill(x, y) 填充绘制科赫雪花。
  • 动画创建和展示
    • FuncAnimation 对象 ani 创建动画,其中 fig 为动画的图形对象,update 为更新函数,frames=np.arange(0, 6) 定义了动画帧的范围(从0阶到5阶),repeat=True 表示动画结束后会重新开始。
    • plt.show() 调用弹出窗口显示动画。
                   

                   

    声明:本公众号分享的前沿学术成果来源于各学术网站,不依法享有其所有权。若原作者发现本次分享中的文字及图片涉及侵权,请立刻联系公众号后台或发送邮件,我们将及时修改或删除!         

    邮箱:environmodel@sina.com         

    若您认为有用,欢迎

    Environmodel设为星标,或

    点击“在看”或“分享”给他人

    Environmodel
    Environmodel(环境模型)专注于环境科学与工程领域的建模及模型研究进展,并分享涵盖机器学习、深度学习以及人工智能等相关领域的理论知识、主流工具和Python编程技巧。
     最新文章