
在 Jupyter(Notebook 或 Lab)中使用 fig.show() 循环生成多个 Plotly 图表时,旧图表可能被自动清除或不可见;本文详解其成因、验证方法及稳定显示全部图表的三种专业解决方案。
在 jupyter(notebook 或 lab)中使用 `fig.show()` 循环生成多个 plotly 图表时,旧图表可能被自动清除或不可见;本文详解其成因、验证方法及稳定显示全部图表的三种专业解决方案。
Plotly 在 Jupyter 环境中默认采用“动态输出”机制:每次调用 fig.show() 会将图表渲染为一个独立的前端组件(plotly-graph-div),但 Jupyter 内核对连续输出单元(尤其是富媒体输出)存在隐式限制——并非 Plotly 本身的硬性限制,而是 Jupyter 前端对重复/高频 application/vnd.plotly.v1+json MIME 类型输出的渲染策略与内存管理行为所致。尤其在旧版 Jupyter Notebook(如 6.x)或特定配置下,系统可能自动折叠、复用或卸载早期输出区域,造成“只看到最后 8 个图”的错觉。
值得注意的是,该问题不具备绝对可复现性:如官方社区验证所示,在 JupyterLab 3.4.8+/4.1.2 或 Notebook 7.1.0+ 中运行以下代码,23 个图表均可正常并列显示:
import plotly.express as px
df = px.data.iris()
for i in range(23):
fig = px.scatter(x=[0,1,2,3,4], y=[i, i+1, i+4, i+9, i+16], title=f"Figure {i+1}")
fig.show()若你仍遇到图表消失现象,说明环境存在兼容性瓶颈(如老旧内核、扩展冲突或资源限制)。以下是三种经生产环境验证的可靠解法:
✅ 方案一:启用 render_mode="iframe"(推荐用于 Notebook)
强制以独立 iframe 渲染每个图表,彻底规避前端 DOM 复用问题:
import plotly.io as pio
pio.renderers.default = "iframe" # 或 "iframe_connected"(需本地服务)
for i in myColumnList:
for j in myColumnList:
fig = px.scatter(df, x=i, y=j, title=f"{i} vs {j}")
fig.show()⚠️ 注意:iframe 渲染器需浏览器支持 iframe,且离线环境可能受限;iframe_connected 更适合交互式调试(需启动本地 Plotly 服务)。
✅ 方案二:批量构建子图(高效 & 轻量)
避免循环 show(),改用 make_subplots 或 facet_col 一次性呈现全部关系:
import plotly.express as px
from plotly.subplots import make_subplots
import plotly.graph_objects as go
# 方法 2a:使用 facet_grid(适用于结构化变量对)
df_long = df.melt(id_vars=df.columns.difference(myColumnList),
value_vars=myColumnList, var_name='variable', value_name='value')
fig = px.scatter(df_long, x='variable', y='value', facet_col='variable', facet_col_wrap=3)
fig.update_layout(title="All Scatter Pairs (Faceted)")
fig.show()
# 方法 2b:手动子图布局(完全可控)
fig = make_subplots(rows=len(myColumnList), cols=len(myColumnList),
subplot_titles=[f"{i} vs {j}" for i in myColumnList for j in myColumnList])
for idx, (i, j) in enumerate([(i,j) for i in myColumnList for j in myColumnList]):
row = idx // len(myColumnList) + 1
col = idx % len(myColumnList) + 1
scatter = go.Scatter(x=df[i], y=df[j], mode='markers', name=f"{i}-{j}")
fig.add_trace(scatter, row=row, col=col)
fig.update_layout(height=400*len(myColumnList), showlegend=False)
fig.show()✅ 方案三:导出为 HTML 并统一打开(适合归档与分享)
将所有图表保存为独立 HTML 文件,再通过 IPython.display.IFrame 或系统命令集中查看:
from IPython.display import IFrame, display
import os
html_files = []
for i in myColumnList:
for j in myColumnList:
fig = px.scatter(df, x=i, y=j, title=f"{i} vs {j}")
filename = f"scatter_{i}_{j}.html"
fig.write_html(filename)
html_files.append(filename)
# 批量嵌入(Jupyter 内显示前 5 个示例)
for html in html_files[:5]:
display(IFrame(html, width="100%", height="500px"))
print(f"✅ 已生成 {len(html_files)} 个 HTML 图表,详见本地目录。")? 总结建议
- 优先升级环境:确保 jupyterlab>=4.0 或 notebook>=7.0 + plotly>=5.15,多数渲染异常可自然消除;
- 避免纯循环 show():它本质是“调试快捷方式”,非生产级可视化方案;
- 按需选择策略:快速探索用 iframe,分析报告用 facet,长期存档用 HTML;
- 禁用冲突扩展:如 jupyter-contrib-nbextensions 中的“Hinterland”或“Variable Inspector”可能干扰输出流,可临时禁用验证。
通过以上任一方法,即可稳定、可扩展地在 Jupyter 中展示任意数量的 Plotly 图表,彻底摆脱“第 9 个图就消失”的困扰。










