数学建模绘图学习笔记

本文最后更新于:2024年7月12日 凌晨

常用的数学建模绘图的方法整理

Python使用Matplotlib进行绘图

基础知识

  • 画板figure,画纸Sublpot画质,可多图绘画
  • 画纸上最上方是标题title,用来给图形起名字
  • 坐标轴Axis,横轴叫x坐标轴label,纵轴叫y坐标轴ylabel
  • 图例Legend 代表图形里的内容
  • 网格Grid,图形中的虚线,True显示网格
  • 点 Markers:表示点的形状。

基础绘图步骤

  • 导入matplotlib的pyplot模块
    1
    import matplotlib.pyplot as plt
  • 用列表定义X、Y坐标轴上的值
  • 绘制图形
    1
    plt.plot(x,y)
  • 显示图形
    1
    plt.show()

一些语法注释:

  • plt.figure(num=1, figsize=(8, 5))
    • num=1: 这个参数指定了新创建的图形窗口的编号,后面可通过 plt.figure(1)来指定或者切换到该图形窗口。
  • ax = plt.gca()
    • plt.gca()用于获取当前图形的坐标轴对象(Axes),返回当前图形中的当前坐标轴对象。可使用返回的坐标轴对象来修改坐标轴的属性、添加标签、设置刻度等。
    • eg:
      ax.set_xlabel(‘X轴标签’)
      ax.set_ylabel(‘Y轴标签’)
      ax.set_title(‘图形标题’)
  • ax.spines[‘right’].set_color(‘none’)
    ax.spines[‘top’].set_color(‘none’)
    隐藏图形中右侧和顶部的坐标轴线条。
    • ax.spines['right'] 表示获取坐标轴对象 ax 中右侧边框(spine)的属性。
      .set_color('none') 表示将右侧边框的颜色设为 ‘none’,即不显示右侧边框线条。

图片属性设置

  • 添加文本
    1
    2
    3
    plt.xlabel('X轴文本')
    plt.ylabel('Y轴文本')
    plt.title('标题文本')
  • 添加注释
    • xy=(5,2):需要注释的点的位置
    • xytext=(2,10):注释文本所在位置
    • arroprops:在xy和xytext之间绘制箭头,shrink表示箭头粗细
      1
      2
      3
      4
      5
      6
      7
      plt.annotate('注释文本',xy=(5,2),xytext=(2,10),arroprops=dict(facecolor='black',shrink=0.01))

      ##复杂一点的注释方式
      plt.annotate(r'$2x+1 = %s$' % y0, xy=(x0, y0), xycoords='data',
      xytext=(+30, -30), textcoords='offset points', fontsize=16
      , arrowprops=dict(arrowstyle='->',
      connectionstyle="arc3,rad=.2"))
  • 绘图属性
    • color:线条颜色,值r表示红色(red)
    • marker:点的形状,值o表示点为圆圈标记(circle marker)
    • linestyle:线条的形状,值dashed表示用虚线连接各点
    • axis:坐标轴范围,语法为axis[xmin, xmax, ymin, ymax]
      1
      2
      3
      4
      plt.plot(x, y, color='r',marker='o',linestyle='dashed')
      #plt.plot(x, y, 'ro')

      plt.axis([0, 6, 0, 20])
  • 把坐标轴换成不同的单位:
    1
    2
    3
    4
    5
    6
    7
    new_ticks = np.linspace(-1,2,5)
    plt.xticks(new_ticks)

    #在对应坐标处更换名称
    plt.yticks([-2,-1,0,1,2],['really bad','b','c','d','good'])
    #把坐标轴上的字体更改成数学符号字体形式
    plt.yticks([-2,-1,0,1,2],[r'$really\ bad$',r'$b$',r'$c\ \alpha$','d','good'])

绘图属性设置

  • 使用legend去区分一个figure中的多条线
    • 如果没有在legend方法的参数中设置label,则必须在画线的plot方法中指定的label参数所指定的名称。都没有的话就会抛出异常;
    • 其实我们plt.plot()的时候返回的是一个线的对象,如果我们想在handle中使用这个对象,就必须在返回的名字的后面加一个,号;
  • 偏移坐标系(offset coordinates)是 Matplotlib 中用于指定文本或注释位置的一种坐标系。在偏移坐标系中,位置相对于指定的点进行偏移。偏移坐标系允许以点(points)为单位指定文本或注释相对于目标点的偏移量。可相对于目标点在水平和垂直方向上进行任意的偏移。
    在 Matplotlib 中,偏移坐标系通过 textcoords=’offset points’ 参数进行指定。然后,使用 xytext 参数来指定相对于目标点的偏移量。
    例如,在 plt.annotate() 函数中,如果您将 textcoords 设置为 ‘offset points’,并且指定了 xytext 参数来指定偏移量,Matplotlib 将使用偏移坐标系来确定注释文本的位置。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #简单的使用图例
    l1, = plt.plot(x, y1, label='linear line')
    l2, = plt.plot(x, y2, color='red', linewidth=1.0, linestyle='--', label='square line')

    #简单的设置legend(设置位置)
    #图例位置显示在右上角
    plt.legend(loc = 'upper right')
    # 自动显示图例位置
    plt.legend(handles = [l1,l2],labels = ['up','down'],loc = 'best')

多图绘制

  • 使用figure()方法创建画板1
  • 使用subplot()方法创建画纸,并选择当前画纸并绘图
    • subplot是子图,subplot(a,b,c),传入三个参数,前两个表示生成几行几列的子图矩阵,最后一个参数表示选择子图1还是2
    • eg. subplot(2,1,1)
  • 同样用subplot()方法选择画纸并绘图:subplot(2,1,2)
  • 显示图形
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #创建画板1
    fig = plt.figure(1) #如果不传入参数默认画板1
    #第2步创建画纸,并选择画纸1
    ax1=plt.subplot(2,1,1)
    #在画纸1上绘图
    plt.plot([1, 2, 3])
    #选择画纸2
    ax2=plt.subplot(2,1,2)
    #在画纸2上绘图
    plt.plot([4, 5, 6])
    #显示图像
    plt.show()

简单的多图绘制

数组绘图

上面部分绘图时传入的数据是列表类型的,但是如果绘制图形只允许传入列表的话,绘制图形会变得很麻烦,因此:

一般传入numpy的数组,实质上所有传入数据的类型在matplotlib内部处理时都会转化为numpy数组类型。

  • 第一步,导入numpy包,再用numpy的一维数组生成一个等差数组,用arange()方法。本例数组中的最小值为0,最大值为5,后一个数据比前一个大0.2。
  • 第二步,定义三个折线图的坐标值,分别用x1,x2,x3表示三个坐标轴上x轴的数值,用y1,y2,y3表示y轴上的数值,这些坐标值都是一维数组。
  • 第三步,绘制图形
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    #导入包numpy
    import numpy as np
    #定义一维数组
    t = np.arange(0, 5, 0.2)

    #使用数组同时绘制多个线性

    #线条1
    x1=y1=t
    #线条2
    x2=x1
    y2=t**2
    #线条3
    x3=x1
    y3=t**3
    #使用plot绘制线条
    linesList=plt.plot(x1, y1,
    x2, y2,
    x3, y3 )
    #用setp方法可以同时设置多个线条的属性
    plt.setp(linesList, r)
    plt.show()
    print('返回的数据类型',type(linesList))
    print('数据大小:',len(linesList))

Line-style 线状图

可用来绘制函数图像,示例代码见文件夹中例程。

Scatter-style 散点图

plt.scatter(X, Y, s=75, c=T, alpha=.5)

  • 使用 Matplotlib 的 scatter() 函数绘制散点图
  • X 和 Y 分别表示散点的 x 和 y 坐标
  • s 表示散点的大小,c 表示散点的颜色,alpha 表示散点的透明度。
  • 设置了 x 轴和 y 轴的显示范围:
    1
    2
    plt.xlim((-1.5,1.5)) 
    plt.ylim((-1.5,1.5))
  • 设置 x 轴和 y 轴的刻度:
    1
    2
    3
    # 这里使用空列表表示不显示刻度
    plt.xticks([])
    plt.yticks([])

最简单的散点图

  • 生成一个大小为 (n_points, 2) 的二维数组,数组中的值在范围 (-1, 9) 内随机分布,代表散点的坐标
    • 使用 NumPy 的 random.random() 函数生成一个大小为 (n_points, 2) 的二维数组,数组中的值是在返回的值范围在 [0, 1)的随机数
    • 表示将生成的随机数组乘以 (10-1) 的范围,即将原始随机数范围缩放到 [0, 9)。
    • -1:将生成的随机数组中的所有元素都减去 1,使得最终的随机数范围从 [-1, 8)。
1
pts = (10-1)*np.random.random(size=(n_points ,2))-1
  • 创建标签字典,将每个标签与其相应的标签名称进行关联

    1
    labels_dict = {0: 'pts_1', 1: 'pts_2', 2: 'pts_3', 3: 'pots_4', 4: 'pts_5'}:
  • 颜色映射规范化对象:将数据范围映射到颜色映射的范围内

    1
    color_norm = colors.Normalize(vmin=0, vmax=4)
  • np.unique():获取数组中唯一的值,并返回排序后的结果

    • np.unique(labels) 将返回一个包含 labels 中唯一值的一维数组,并按照从小到大的顺序排列这些值。这个数组中的值将用于确定要显示的类别数量,并在后续的处理中用作索引。
  • size=pts.shape[0] 表示生成的随机数数组的大小与 pts 数组的第一个维度相同,也就是 n_points

  • cmap=cm.Set1: 这是指定的颜色映射。

    • 使用 cm.Set1 颜色映射,它是 Matplotlib 库中提供的一种颜色映射,包含了一组离散的颜色,适合用于区分不同的分类标签。
  • enumerate(unique_labels) 是 Python 中的一个内置函数,它接受一个可迭代对象(例如列表、元组、字符串等)作为参数,并返回一个由索引和值组成的枚举对象,索引从 0 开始。

    • unique_labels 是一个包含数据集中唯一标签的数组。因此在循环中能够同时访问标签的索引和值,方便对数据进行处理。
    • 例如,如果 unique_labels 是 [0, 1, 2, 3, 4],则 enumerate(unique_labels) 返回的枚举对象将是 [(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)]。

有筛选规则的散点图

  • mask = np.where(labels == label)[0]:
    用于找到数组 labels 中与特定标签值 label 相匹配的索引
    • np.where() 函数接受布尔数组作为参数,返回一个元组,其中包含满足条件的元素的索引。
    • [0] 表示从返回的元组中取出索引数组,因为 np.where() 返回的是一个元组,包含所有满足条件的索引数组。通常情况下,我们只需要第一个满足条件的索引数组,因此使用 [0] 来取出。
  • 选取二维数组 pts 中的所有行,但只选取第一列(X)/第二列(Y)的数据
    1
    2
    pts[:, 0][mask]
    pts[:, 1][mask]
  • [mask] 使用布尔掩码 mask 来过滤选取的数据
    • 布尔掩码 mask 是一个布尔数组,其长度与数组 pts 的行数相同。对于数组 pts[:, 0] 和 pts[:, 1] 中的每个元素,如果对应位置的 mask 元素为 True,则相应的元素会被选中,否则会被忽略

柱状图

python制作的柱状图

代码解释:

  • X = np.arange(n)
    • 创建一个包含0到n-1的数组,用作柱子的位置
  • 分别定义两组与X对应的柱子高度:Y1,Y2
  • plt.bar(X, +Y1, facecolor='#9999ff', edgecolor='white')
    • 创建一组柱状图,位于X位置,高度为Y1,面颜色为蓝色,边框颜色为白色
    • 同理,plt.bar(X, -Y2, facecolor='#ff9999', edgecolor='white')
      创建另一组柱状图,位于X位置,高度为-Y2,面颜色为红色,边框颜色为白色
  • 添加文字标签:
    • 通过循环遍历每个柱子的位置和高度,并在相应位置添加文字标签。
      1
      2
      3
      4
      5
      6
      7
      for x, y in zip(X, Y1):
      # 在柱子的顶部添加高度值,水平对齐方式为'center',垂直对齐方式为'bottom'
      plt.text(x + 0.01, y + 0.05, '%.2f' % y, ha='center', va='bottom')

      for x, y in zip(X, Y2):
      # 在柱子的底部添加高度值,水平对齐方式为'center',垂直对齐方式为'top'。
      plt.text(x + 0.01, -y - 0.05, '%.2f' % (-y), ha='center', va='top')
  • 设置x轴和y轴的范围
    1
    2
    3
    4
    # 设置x轴的范围为从-0.5到n
    plt.xlim(-.5, n)
    # 设置y轴的范围为从-1.25到1.25
    plt.ylim(-1.25, 1.25)
  • 隐藏y轴刻度: plt.yticks([])

双侧柱状图

excel制作的柱状图

参考:
https://zhuanlan.zhihu.com/p/78646791

python绘制正态分布的直方图和概率密度函数曲线

  • np.random.normal():生成指定均值和标准差的正态分布随机数。
    1
    2
    gaussian_numbers_1 = np.random.normal(size=100000)
    gaussian_numbers_2 = np.random.normal(3, 2, size=100000)
  • 绘制正态分布的直方图和概率密度函数曲线
    • 绘制 gaussian_numbers_1 的直方图,并使用 mlab.normpdf()函数计算了该分布的概率密度函数曲线
    • 直方图的参数设置包括:直方条的数目 (bins)直方图的类型 (histtype)直方条的宽度 (rwidth)是否进行归一化 (normed)颜色和透明度 (color 和 alpha)
    • 在 plt.hist() 函数中,nbinspatches 是返回的三个值。
      • n: 是一个长度为 len(bins) - 1 的数组,其中每个元素代表了在对应区间内的数据点数量
      • bins: 是一个包含直方图柱子边界值的数组。直方图通常是基于数据的范围和分布,被分割成若干个区间,这些区间就是通过 bins 参数指定的。
      • patches: 是一个包含所有直方图柱子的列表,每个柱子是一个图形对象,你可以通过修改它们的属性来自定义柱子的外观。
1
n, bins, patches = plt.hist(gaussian_numbers_1, bins=30, histtype='bar', rwidth=0.8, normed=1, color='g', alpha=0.5, label='Gaussian_1')

正态分布的直方图和概率密度函数曲线

权重图、热力图、三维地图

表示相关位置的重要程度。

权重图

一般用excel的色阶工具,加上PPT的修饰。

  • excel列出表格数据,色阶着色
  • 复制到PPT,选择原格式粘贴
  • 使用PPT的布局调整宽度和长度,以及数据的对齐方式
  • 使用PPT的表设计,可以加边框(设置颜色和粗细,选定数据加边框)
    • 表设计里面的底纹,可以选渐变等样式

色阶图

热力图和三维地图

  1. 使用python:

更新:使用PyCharm一样可以直接得到地图,但是需要保存为本地heml文件。详细教程参考:https://cloud.tencent.com/developer/article/2165996\
(我更喜欢PyCharm这个IDE,所以使用的是这个教程,不过大概操作都差不多;里面还有一个实战案例)

  1. 使用excel制作:

热力图

  • 选中excel表格数据,选择“三维地图”,默认场景为地球,可“选择新场景--新建自定义地图--浏览背景图片”。在图层1中选择位置x,y对应x,y坐标,数据会自动调整最值和缩放比例。选择热力图形式,在图层选项里面调整色阶和影响半径。最后点击捕获屏幕就可以导出最后的图像。

  • 选中excel表格数据,选择“三维地图”,默认场景为地球,可以选择平面地图把它展平。

三维地图

等高线图

一些代码解释:

  • 使用NumPy的linspace函数在区间[-3, 3]上生成n个等间距的点,作为x轴、y轴上的坐标点
    1
    2
    3
    n = 256
    x = np.linspace(-3, 3, n)
    y = np.linspace(-3, 3, n)
  • 使用meshgrid函数将x和y上的点在二维平面上画网格
    • X和Y是生成的网格点的二维数组
      1
      X, Y = np.meshgrid(x, y)
  • 使用contourf函数填充等高线图颜色
    • X和Y是网格点的坐标,f(X, Y)是对应的高度值,8表示等高线分成8个部分,alpha=.75表示填充颜色的透明度为0.75,cmap=plt.cm.hot表示使用热度图颜色。
      1
      plt.contourf(X, Y, f(X, Y), 8, alpha=.75, cmap=plt.cm.hot)
  • 使用contour函数添加等高线
    • 指定线的颜色为黑色,线宽为0.5
      1
      2
      # 形参分别为:X,Y,Z(高度),等高线的级别数量,等高线颜色,线宽
      C = plt.contour(X, Y, f(X, Y), 8, colors='black', linewidth=.5)
  • 添加等高线的标签
    • inline=True表示将标签嵌入等高线之中,fontsize=10表示标签的字体大小为10
      1
      plt.clabel(C, inline=True, fontsize=10)

等高线图

复杂一点的多图合一

使用python实现色阶

  • plt.imshow(a,interpolation = 'nearest',cmap = cm.jet ,origin = 'upper'):
    • origin 参数用于确定数组数据的原点位置,通常是在图像的左上角或左下角。Matplotlib 中支持的值是 upperlower
    • a: 是要显示的图像数据,通常是一个二维的数组,每个元素代表一个像素的值
    • interpolation='nearest' 这个参数指定了图像数据的插值方式。 'nearest' 表示使用最近邻插值,即使用最近的像素值来填充图像的空白部分。这意味着图像的显示会更加锐利,但可能会失去一些平滑性。
    • cmap='bone' 这个参数指定了颜色映射,即将数据值映射到颜色的方式。
      在这里,'bone' 是 Matplotlib 中提供的一种颜色映射方案,它会将数据值映射为灰度色调,其中较小的值会显示为较暗的颜色,较大的值会显示为较亮的颜色。
      也可使用cmap = cm.jet,将数据值映射为彩虹色的颜色>(需要先import matplotlib.cm as cm)
    • cm是matplotlib.cm模块的别名,它包含了许多预定义的颜色映射。
  • plt.colorbar(shrink = .92)
    • 显示色条,可设置宽度shrink。

复杂一点的图

office制作散点图

matlab,python,office都可以制作散点图。

散点图

  1. office制作散点图:难度低,但是需要做的生动形象,就需要一些技巧了。
  • 更换散点为小球啥的,看起来新颖一点:
    选择散点图里面的散点-设置数据系列格式-选择标记-标记选项-把大小调成合适的小球的大小-在网上找到小球的图片,复制到剪贴板-在填充选择图片或纹理填充-剪贴板-在边框可以设置无线条
  • 更换背景使之更符合问题背景:
    设置绘图区格式里面-选择填充-图片或纹理填充-插入图片
  • 补充的一些office制作图表技巧:
    • 切换x,y轴: 自己百度去。
    • 调整坐标轴的范围使数据点分布均匀一点:
      设置图标区格式里的图表选项-选择垂直轴选项-坐标轴选项-设置边界
    • 坐标轴可以设置刻度线啥的,好看一点的话就是主刻度线交叉次刻度线内部
    • PPT里面不同形状可以组合图形,互补互切啥的。

着色图表

着色图表

使用方法:Matlab or Excel +PPT

普通折线图、线性拟合图——点实线透明,色彩对比鲜明

推荐把点的颜色设置得比较深,把线的颜色设的稍浅,显得更有层次感。
不同线之间颜色选择:

  • 对比色
  • 同色系的不同色调(一大段有多张相似图表,每张图选择一个色系)
  • matlab/excel就可以实现。

面积图——实际上就是在一块面积内填渐变色

  1. 利用office自带的面积图叠一层:
  • 优点:简单方便,只要把数据复制一遍选择面积图即可。
  • 缺点:office的曲线图带有平滑拟合,而面积图无平滑拟合,所以会有留白。
  1. 使用PS处理 (自己百度去)

注意:不要滥用渐变色、透明度、阴影、虚线、发光,色彩搭配要注意不能显得太廉价。

突出对比的智能图表(雷达图,漏斗图,条形图)

office自带了丰富的图表类型!!!

利用插件制作图表

常用的插件:

  • iSlide插件
    设计排版中的矩阵布局环形布局很好用;有丰富的案例库,主题库,图示库,智能图表,图标库……
  • 口袋动画PA插件:主要是做动画的,其中的矢量工具很好用

流程图&层次图

流程图

流程图

数据3D可视化(python)

需要导入的库:

1
2
3
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

流程解释:

  • 创建图形和三维坐标轴,设置图片尺寸和分辨率
    1
    2
    fig = plt.figure(figsize=plt.figaspect(0.6))
    ax3 = fig.add_subplot(1, 1, 1, projection='3d')
  • 生成数据
    • 生成一个二维的网格 X 和 Y,然后计算了对应于网格点的 R(距离原点的距离),最后通过正弦函数生成了 Z 值
      1
      2
      3
      4
      5
      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)
  • 绘制三维曲面图
    • plot_surface() 用于绘制三维曲面图,参数中的 X、Y、Z 分别表示数据的坐标,rstridecstride 控制行和列的采样间隔cmap 指定了颜色映射。
      1
      ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=plt.get_cmap('rainbow'))
    • 绘制等高线图
      • contourf() 用于绘制等高线图,参数中的 X、Y、Z 表示数据的坐标,zdir 指定了等高线图的方向(这里是垂直于 Z 轴的方向),offset 指定了等高线图的位置偏移cmap 指定了颜色映射
    ax.contourf(X, Y, Z, zdir='z', offset=-2, cmap=plt.get_cmap('rainbow'))
    
  • 设置 Z 轴的范围:ax.set_zlim(-2, 2)

3D海域深度图

三维立体图(PPT就可以制作)

  1. 图标素材的来源:
  • 阿里巴巴
  • Office自带图标
  • iSlide插件的图标库
  1. 三维绘图的关键点:形状效果的棱台和三维旋转
  • 棱台注意调节深度、光线、材质等。(调节凭感觉)
  • 各种材质的小球可以使用棱台效果调节宽度得到
  • 图标库里面的二维小人,可以添加棱台效果使之变得立体一点
  • 三维旋转XYZ轴的调节是玄学……

三维立体图1

三维立体图2

铅笔画、素描画

使用工具:PPT里面的艺术效果:
选中图片——菜单栏的图片格式——调整工具栏的艺术效果——艺术效果选项——微调一下:透明度、压力、铅笔大小


数学建模绘图学习笔记
http://zoechen04616.github.io/2023/09/02/数学建模绘图学习笔记/
作者
Yunru Chen
发布于
2023年9月2日
许可协议