Julia:如何用 Plots 画多个子图

简介: Plots 可以画出很多丰富的图。从画线、点、阴影填充都可以,但是在 Julia 上面,与 Python 上的 Matplotlib 的写法有很大的不同,这篇文章就是写一些基本的或者常用的用法,包括如何用 For 循环去画多个子图。

Plots 可以画出很多丰富的图。从画线、点、阴影填充都可以,但是在 Julia 上面,与 Python 上的 Matplotlib 的写法有很大的不同,这篇文章就是写一些基本的或者常用的用法,包括如何用 For 循环去画多个子图。

今天就来学习如何使用 Plots 灵活地画图,以不同的高斯分布图作为例子。

1/ 创建高斯分布概率密度

using Random, Distributions, Plots
Random.seed!(123);

x = collect(-8:0.5:8);
y_gaussian = zeros(length(x), 8)
mu = [0., 0.5, 1., 1.5, 2., 2.5, 3., 3.5]
sig = [1., 1.2, 1.4, 1.6, 1.6, 1.4, 1.2, 1.]
for i in 1:8
    y_gaussian[:, i] = pdf.(Normal(mu[i], sig[i]), x)
end

使用 Distributions 可以创建高斯分布概率密度图,先生成 8 个高斯分布的参数,分别为 mu, sig 数组,然后通过循环生成 8 个高斯概率密度分布,保存在 y_gaussian 上以待画图。

2/ 画出高斯分布图

我们的目标是,将八个高斯分布分成两行四列画出来,并且每一行,只有第一列显示 Y 轴刻度,即同一行的图共享 Y 坐标轴刻度,线的标签在小图里不画出来。

最后在图的下半部分,把所有的高斯分布一起画出来,并且显示标签。最终显示的效果如下:

思路就是从上到下是四个图,分别为标题、上面四个小图、中间四个小图和最下面的一个大图,所以这个图是子图套子图。

2.1/ 循环建立子图

为了方便,写一个函数,可以一次性完成一行四个小图的建立:

function plot_gaussians(x::Array, y::Array, colors)
    figures = Any[];
    nums = size(y)[2];
    ymax = maximum(y);
    yticks_attri = [true; fill(false, nums-1)];
    for i in 1:nums
        f = plot(x, y[:, i],
                 ylim=(0, ymax), label=false, grids=false,
                 yticks=yticks_attri[i], color=colors[i]);
        push!(figures, f);
    end
    return plot(figures..., layout=(1, 4));
end

第一种画子图的方式,就是把子图一个一个放进一个数组,然后最后画出来。

函数 plot_gaussians(x::Array, y::Array, colors),接受参数 x, y 分别为 X 的坐标和高斯分布矩阵,colors 为每个高斯分布的画出来的颜色。

首先生成一个变量 figures=Any[] 待存放所有的子图。因为只有每一行的第一个图需要 Y 刻度,所以生成了一个数组 yticks_attri = [true; fill(false, nums-1)]; 记录 yticks 的属性。

在画图的时候,将关键词 yticks设为 false 就可以不显示坐标轴刻度,所以遍历每个高斯分布,然后让 yticks=yticks_attri[i]

因为要共享 Y 坐标轴,所以先 ymax = maximum(y); 得到 Y 轴的最大值,然后使用 ylim=(0, ymax) Y 轴的显示范围。

label=false, grids=false 这两个关键词是不显示线条的标签,然后图的背景不显示交叉的虚线。

关键的两步是,使用 push!(figures, f); 把当前子图放进 figures 里面,然后用 plot(figures..., layout=(1, 4)); 生成一个大的图。

...:「splat」运算符, ... 表示参数序列。该参数可以用于函数定义,以指示函数接受任意数量的参数;还可用于将函数应用于参数序列。

2.2/ 手动建立子图

另外用于建立子图的一种方法,就是自己一个一个手动写出来,与上面的区别就是,上一种是把图放进一个列表,然后利用 ... 运算符,这种情况适用于子图的数量是不定的时候,或者是可变,可循环的情况。

我们上面写了一个函数,接下来就是把各个小的子图组合成一个大图。

需要注意的是,在 Plots 里面图的标题只能是为小图写的,如果要为整个大图添加标题,那么就只能弄一个图,只包含了标题的,去掉其他元素的。

title = plot(title="Gaussian pdf Plot", framestyle=nothing, grid=false, showaxis=false, ticks=false, bottom_margin=-25Plots.px); 这一句就是创建大的标题,然后将坐标轴,边框啥的不要的元素都去掉,最后放在大图的上面就行了。

然后利用写好的函数 plot_gaussians 生成两个子图 f1, f2

colors = reshape(palette(:tab10)[:], 1, :);
title = plot(title="Gaussian pdf Plot", framestyle=nothing, grid=false,
             showaxis=false, ticks=false, bottom_margin=-25Plots.px);
f1 = plot_gaussians(x, y_gaussian[:, 1:4], colors[1:4]);
f2 = plot_gaussians(x, y_gaussian[:, 5:end], colors[4:end]);
labels = reshape(["$(m), $(s)" for (m, s) in zip(mu, sig)], 1, :)
f3 = plot(x, y_gaussian, grids=false, label=labels, legend=:left, color=colors[:, 1:8]);
l = @layout([a{0.01h}; grid(3, 1, heights=[0.25 ,0.25, 0.5])])
plot(title, f1, f2, f3, layout=l, size(800, 600))
savefig("line.pdf")

我将整个大图分成两个部分进行布局,第一部分为标题(title),在最上面,给其一个比较窄的位置,然后下面是 3 行的区域,两个小子图为 0.25 的宽度,大图占一半,所以布局用宏表示为 l = @layout([a{0.01h}; grid(3, 1, heights=[0.25 ,0.25, 0.5])]).

最后画出最终的图,前面的变量,可以一个一个添加进入,plot(title, f1, f2, f3, layout=l, size(800, 600))

保存图片 savefig("line.pdf"),最终结果:

目录
相关文章
|
6月前
|
编解码 并行计算 算法
MPI分形图像高精度绘制程序和PC端Mandelbrot-Julia分形集预览程序
这篇文章描述了一个使用2010年技术的集群程序,该程序基于Linux + MPI + C++或Windows + .NET + C#,用于并行计算生成高分辨率BMP图像,特别是Mandelbrot和Julia集。在8台节点上,程序实现了7.31的稳定加速比,并在更大规模任务中有望提升。它支持MPI并行计算、任务日志、不同阶数的分形集生成、批处理、多线程以及优化的颜色处理等功能。创新点包括颜色表的正弦控制、动态调整运算精度、复杂颜色生成、优化的颜色更新和并发机制等。程序产生的图像样本显示了其多样性和质量。作者提供源代码,并提到设计思路可应用于类似图像生成任务。
|
5月前
|
机器学习/深度学习 编解码 数据可视化
图神经网络版本的Kolmogorov Arnold(KAN)代码实现和效果对比
目前我们看到有很多使用KAN替代MLP的实验,但是目前来说对于图神经网络来说还没有类似的实验,今天我们就来使用KAN创建一个图神经网络Graph Kolmogorov Arnold(GKAN),来测试下KAN是否可以在图神经网络方面有所作为。
201 0
|
6月前
|
算法 计算机视觉 异构计算
基于FPGA的图像一维FFT变换IFFT逆变换verilog实现,包含tb测试文件和MATLAB辅助验证
```markdown ## FPGA 仿真与 MATLAB 显示 - 图像处理的 FFT/IFFT FPGA 实现在 Vivado 2019.2 中仿真,结果通过 MATLAB 2022a 展示 - 核心代码片段:`Ddddddddddddddd` - 理论:FPGA 实现的一维 FFT/IFFT,加速数字信号处理,适用于高计算需求的图像应用,如压缩、滤波和识别 ```
|
7月前
|
计算机视觉
LabVIEW在 XY Graph中选择一组点
LabVIEW在 XY Graph中选择一组点
40 2
|
7月前
|
存储 缓存 算法
基于FPGA的二维DCT变换和逆变换verilog实现,包含testbench
基于FPGA的二维DCT变换和逆变换verilog实现,包含testbench
|
算法 异构计算
基于FPGA的FFT变换和反变换实现,使用IP核设计,包含testbench
基于FPGA的FFT变换和反变换实现,使用IP核设计,包含testbench
317 0
|
机器学习/深度学习 算法 数据挖掘
图(Graph)--概念及应用
本文分享了关于图的概念、图的数学表示及图的应用等内容,以供参考学习
325 0
|
数据可视化 数据挖掘 Python
跟着Molecular Plant学作图:R语言circlize包画圈图展示基因组的一些特征补充添加图例
跟着Molecular Plant学作图:R语言circlize包画圈图展示基因组的一些特征补充添加图例
|
算法 异构计算
m基于FPGA的分布式FIR滤波器verilog设计,对比普通结构以及DA结构
m基于FPGA的分布式FIR滤波器verilog设计,对比普通结构以及DA结构
193 0
m基于FPGA的分布式FIR滤波器verilog设计,对比普通结构以及DA结构
|
机器学习/深度学习 编解码 算法
异构图 Link 预测 理论与DGL 源码实战
异构图 Link 预测 理论与DGL 源码实战
异构图 Link 预测 理论与DGL 源码实战