Plotly多图表同页展示:循环调用绘图函数实现2列4行布局
使用Plotly Subplot实现4行2列紧凑布局的解决方案
核心思路
Plotly Subplot的本质是将多个图表的Trace对象整合到同一个Figure中,而非直接拼接独立的Figure。所以你需要调整自定义函数的输出,或者从已生成的Figure中提取Trace,再逐个添加到对应子图位置。
方案1:修改自定义绘图函数返回Trace(推荐)
如果可以修改charting_func,让它直接返回绘图所需的Trace对象(而非完整Figure),这样能更高效地整合到Subplot中:
调整后的绘图函数示例
import plotly.graph_objects as go def charting_func(data): # 仅返回Trace对象,而非创建完整Figure return go.Scatter( x=data["x"], y=data["y"], mode="lines+markers", name=f"Data {data['id']}" )
主代码实现4x2布局
from plotly.subplots import make_subplots # 假设你有8组待可视化的数据,存储在data_list中 data_list = [ {"id": 1, "x": [1,2,3], "y": [4,5,6]}, {"id": 2, "x": [1,2,3], "y": [6,5,4]}, # ... 其余6组数据 ] # 创建4行2列的Subplot布局,设置紧凑间距 fig = make_subplots( rows=4, cols=2, subplot_titles=[f"Chart {i+1}" for i in range(8)], vertical_spacing=0.07, # 缩小垂直间距 horizontal_spacing=0.09, # 缩小水平间距 specs=[[{"type": "scatter"} for _ in range(2)] for _ in range(4)] ) # 循环调用函数并添加Trace到对应子图 for idx, data in enumerate(data_list): # 计算当前子图的行/列号(Plotly子图索引从1开始) row = (idx // 2) + 1 col = (idx % 2) + 1 # 获取Trace并添加到Subplot trace = charting_func(data) fig.add_trace(trace, row=row, col=col) # 调整整体布局,进一步优化紧凑度 fig.update_layout( height=1100, # 根据子图数量设置合适高度 width=900, title_text="8 Charts in Compact 4x2 Layout", margin=dict(l=30, r=30, t=60, b=30), # 缩小边距 showlegend=False # 如果不需要统一图例可以隐藏 ) # 统一设置坐标轴标题(按需调整) fig.update_xaxes(title_text="X Value", row=4, col=1) fig.update_xaxes(title_text="X Value", row=4, col=2) fig.update_yaxes(title_text="Y Value", row=1, col=1) fig.update_yaxes(title_text="Y Value", row=1, col=2) fig.show()
方案2:不修改原函数,从返回的Figure中提取Trace
如果无法修改charting_func(它直接返回完整Figure),可以从每个生成的Figure中提取Trace,再添加到Subplot:
主代码示例
from plotly.subplots import make_subplots import plotly.graph_objects as go # 假设原绘图函数是这样的(无法修改) def charting_func(data): fig = go.Figure() fig.add_trace(go.Scatter(x=data["x"], y=data["y"])) fig.update_layout(title=f"Chart {data['id']}") return fig data_list = [ {"id": 1, "x": [1,2,3], "y": [4,5,6]}, # ... 其余7组数据 ] # 创建Subplot布局 fig = make_subplots( rows=4, cols=2, vertical_spacing=0.07, horizontal_spacing=0.09 ) for idx, data in enumerate(data_list): row = (idx // 2) + 1 col = (idx % 2) + 1 # 调用原函数得到独立Figure sub_fig = charting_func(data) # 提取所有Trace并添加到对应子图 for trace in sub_fig.data: fig.add_trace(trace, row=row, col=col) # 同步子图的坐标轴标题(如果原函数有设置) fig.update_xaxes(title_text=sub_fig.layout.xaxis.title.text, row=row, col=col) fig.update_yaxes(title_text=sub_fig.layout.yaxis.title.text, row=row, col=col) # 调整整体布局 fig.update_layout( height=1100, width=900, margin=dict(l=30, r=30, t=60, b=30) ) fig.show()
关键注意事项
- Plotly的子图索引从1开始,所以循环中计算行/列时要+1
- 通过
vertical_spacing和horizontal_spacing参数控制子图间距,数值越小布局越紧凑 - 如果需要统一设置样式(如坐标轴、字体),直接在主Figure上用
update_xaxes/update_yaxes批量修改
内容的提问来源于stack exchange,提问作者Riccardo
相关产品推荐
相关产品推荐

