在阅读文献或处理数据时,我们经常会见到或用到下图这类常规排列的子图,这类子图一般可以使用Python的matplotlib库或MATLAB的subplot函数进行绘制。
那么对于下面这类复杂排布的子图应该使用什么方法呢?
下面将分别介绍如何在Python及MATLAB中绘制复杂排布的子图。
Python
matplotlib
subplot_mosaic
是 Matplotlib 库中的一个功能,它允许你以一种相对简单的方式创建复杂的图形布局。使用 subplot_mosaic
, 你可以通过指定一个字符串的 “马赛克” 来定义子图(subplots)的布局。每个字符代表一个子图的位置,相同的字符代表同一个子图。
这种方式比传统的 subplot
方法更灵活,特别是在创建非标准或不规则布局的时候。
例如,如果你想创建下图所示的子图格式,你可以使用如下的马赛克模式:
subplot_mosaic(
"""
ABD
CCD
"""
)
此处使用了“A、B、C、D”指代了每个子图的位置,同理可使用不同的名称进行指代,只要保持正确的相对位置关系即可。
如果遇到需要空出位置的情况,使用.
代表空白位置即可。
subplot_mosaic(
"""
A.C
BBB
.D.
"""
)
下面通过一个简单的案例进行展示:
import matplotlib.pyplot as plt
import numpy as np
# 示例数据
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)
data3 = np.random.normal(size=1000)
data4 = np.random.rand(10, 5)
# 定义复杂、不规则的子图布局
layout = [
["line plot", "scatter plot", "scatter plot"],
["line plot", "histogram", "box plot"],
["line plot", "histogram", "box plot"]
]
# 创建子图
fig, axs = plt.subplot_mosaic(layout, figsize=(12, 8))
# 第一个子图:折线图
axs['line plot'].plot(x, y1)
axs['line plot'].set_title('Sin(x) Line Plot')
# 第二个子图:散点图
axs['scatter plot'].scatter(x, y2)
axs['scatter plot'].set_title('Cos(x) Scatter Plot')
# 第三个子图:直方图
axs['histogram'].hist(data3, bins=20)
axs['histogram'].set_title('Histogram')
# 第四个子图:箱线图
axs['box plot'].boxplot(data4)
axs['box plot'].set_title('Box Plot')
plt.tight_layout()
plt.show()
MATLAB
使用 tiledlayout 和 nexttile(推荐)
从 MATLAB R2019b 版本开始,tiledlayout
和 nexttile
函数提供了一种更灵活的方式来创建网格布局。
这些函数允许你创建一个包含多个子图的网格,并且可以很容易地合并行或列。
例如使用tiledlayout
和 nexttile
实现上一节的案例:
% 生成数据
x = linspace(0, 10, 100);
y1 = sin(x);
y2 = cos(x);
data3 = randn(1, 1000);
data4 = rand(5, 10);
% 创建非规则布局
tiledlayout(3,3)
% 第一个子图:折线图
nexttile(1,[3,1])
plot(x, y1);
title('Sin(x) Line Plot');
% 第二个子图:散点图
nexttile([1,2])
scatter(x, y2);
title('Cos(x) Scatter Plot');
% 第三个子图:直方图
nexttile([2,1])
histogram(data3);
title('Histogram');
% 第四个子图:箱线图
nexttile([2,1])
boxplot(data4');
title('Box Plot');
使用subplot函数
在 MATLAB 中,使用 subplot
函数直接实现像 tiledlayout
/nexttile
或 Matplotlib 的 subplot_mosaic
那样的复杂布局是比较困难的,特别是当涉及到跨越多行或多列的子图时。
subplot
函数更适合于标准的网格布局,其中每个子图占据网格中的一个单元。
subplot
函数通过三个参数定义子图的位置:网格的行数、列数和子图应该放置的位置编号。例如,subplot(2, 3, 1)
会在一个 2 行 3 列的网格中创建一个子图,并将其放置在第一个位置。
要在使用 subplot
的情况下创建类似的布局(例如,底部的子图跨越所有列),你需要在适当的位置调用 subplot
函数多次来创建单独的轴。这种方法通常会导致代码更加复杂和不那么直观。
下面是如何使用 subplot
绘制上文的案例:
% 生成数据
x = linspace(0, 10, 100);
y1 = sin(x);
y2 = cos(x);
data3 = randn(1, 1000);
data4 = rand(5, 10);
% 创建非规则布局
figure;
% 第一个子图:折线图
subplot(3, 3, [1, 4, 7]);
plot(x, y1);
title('Sin(x) Line Plot');
% 第二个子图:散点图
subplot(3, 3, [2, 3]);
scatter(x, y2);
title('Cos(x) Scatter Plot');
% 第三个子图:直方图
subplot(3, 3, [5,8]);
histogram(data3);
title('Histogram');
% 第四个子图:箱线图
subplot(3, 3, [6, 9]);
boxplot(data4');
title('Box Plot');