如何用循环实现6×4子图批量绘制421个图并每24个生成新图像?
解决6×4子图分组绘制421个图形的问题
我完全懂你的困扰——你本来想把421个图形按6行4列的子图布局,每24个打包成一张独立的图片,但之前的代码只是逐个画出单独的折线图,结果全堆成了纵向排列的单图,完全没实现预期的分组布局。
先分析你原有代码的问题
你的循环里每次直接调用plt.plot()和plt.show(),这会让Matplotlib为每个图形单独创建一个画布,自然就变成了逐个纵向排列的独立窗口,完全没用到子图布局的逻辑。
解决方案代码实现
下面是调整后的代码,核心思路是按24个图形为一组,每组创建一个6×4的子图画布,绘制完一组后保存/展示,再处理下一组:
import matplotlib.pyplot as plt import numpy as np # 总图形数量 total_plots = 421 # 每组子图数量:6行×4列=24个 plots_per_figure = 6 * 4 # 计算需要多少张图(向上取整) total_figures = (total_plots + plots_per_figure - 1) // plots_per_figure # 循环处理每一组图形 for fig_idx in range(total_figures): # 计算当前组的起始和结束索引 start_idx = fig_idx * plots_per_figure end_idx = min(start_idx + plots_per_figure, total_plots) # 创建6×4的子图布局,设置合适的画布大小 fig, axes = plt.subplots(nrows=6, ncols=4, figsize=(16, 12)) # 将axes转换为一维数组,方便循环遍历 axes = axes.flatten() # 遍历当前组的每个图形 for plot_idx in range(end_idx - start_idx): current_data_idx = start_idx + plot_idx a = df.iloc[current_data_idx:current_data_idx+1] # 提取数据并拼接 x = np.concatenate([ a['t11_arms_number_a31_1_weighted_fraction'], a['t11_arms_number_a32_2_weighted_fraction'], a['t11_arms_number_a33_3_weighted_fraction'], a['t11_arms_number_a34_4_weighted_fraction'], a['t11_arms_number_a36_more_than_4_weighted_fraction'], a['t11_arms_number_a37_cant_tell_weighted_fraction'] ]) y = np.linspace(1, 6, 6) # 在对应的子图上绘制折线 ax = axes[plot_idx] ax.plot(y, x) # 可以给每个子图加标题,方便识别 ax.set_title(f'Plot {current_data_idx + 1}') # 调整坐标轴标签(按需添加) ax.set_xlabel('Y Axis') ax.set_ylabel('X Value') # 处理最后一组不足24个的情况:隐藏多余的空坐标轴 for empty_ax in axes[end_idx - start_idx:]: empty_ax.axis('off') # 调整子图间距,避免重叠 plt.tight_layout() # 保存当前组的图片(可选,替换成你想要的路径和格式) plt.savefig(f'grouped_plots_{fig_idx + 1}.png', dpi=100) # 展示当前组的图片 plt.show() # 关闭当前画布,释放内存 plt.close(fig)
关键细节说明
- 分组逻辑:用整数除法向上取整计算总画布数,确保所有421个图形都能被覆盖。
- 子图布局:
plt.subplots(6,4)直接创建6行4列的子图网格,flatten()把二维的axes数组转成一维,方便按顺序遍历。 - 空坐标轴处理:最后一组不足24个时,把多余的子图坐标轴隐藏,让画面更整洁。
- 内存管理:每次绘制完一组后调用
plt.close(fig),避免Matplotlib占用过多内存。
内容的提问来源于stack exchange,提问作者Yash Lapasia
相关产品推荐
相关产品推荐

