在 Jupyter(Notebook 或 Lab)中使用 fig.show() 循环绘制多个 Plotly 图形时,旧图被自动清除是常见现象,本质源于前端渲染限制与输出缓冲机制;本文提供稳定显示全部图形的三种可靠方案。
在 jupyter(notebook 或 lab)中使用 `fig.show()` 循环绘制多个 plotly 图形时,旧图被自动清除是常见现象,本质源于前端渲染限制与输出缓冲机制;本文提供稳定显示全部图形的三种可靠方案。
Plotly 在 Jupyter 环境中默认以独立交互式组件形式渲染图形,每次调用 fig.show() 会将新图形插入当前 cell 的输出区域。当输出内容过多(尤其是大型交互式 HTML 组件)时,Jupyter 前端(特别是旧版 Notebook 内核或某些浏览器环境)可能触发输出截断、内存回收或 DOM 节点复用策略——这正是用户观察到“超过 8 个图后旧图消失”的根本原因。值得注意的是,该行为并非 Plotly 本身的 Bug,而是 Jupyter 输出系统对大量富媒体内容的保守处理机制;实际可支持的图形数量取决于环境配置(如 jupyter-server 版本、前端渲染引擎、浏览器内存限制),而非硬编码阈值。
✅ 推荐解决方案如下(按优先级排序):
1. 使用 plotly.graph_objects.FigureWidget(适用于需交互+持久化场景)
FigureWidget 将图形作为可更新的前端对象嵌入,避免重复创建输出单元,天然规避截断问题:
import plotly.express as px
import plotly.graph_objects as go
from IPython.display import display
df = px.data.iris()
myColumnList = ['sepal_length', 'sepal_width', 'petal_length', 'petal_width']
for i in myColumnList:
for j in myColumnList:
if i != j: # 避免自相关图
fig = px.scatter(df, x=i, y=j, title=f'{i} vs {j}')
# 使用 FigureWidget 替代 fig.show()
widget = go.FigureWidget(fig)
display(widget) # 每次 display 创建独立输出槽位⚠️ 注意:FigureWidget 在 JupyterLab 中需安装 jupyterlab-plotly 扩展(pip install jupyterlab-plotly && jupyter labextension install jupyterlab-plotly),Notebook 中通常开箱即用。
2. 合并为子图(Subplots)——最高效、最专业的可视化实践
若目标是批量对比,强烈建议将多图整合进单个 make_subplots 容器,显著降低前端负载并提升可读性:
from plotly.subplots import make_subplots
import plotly.express as px
df = px.data.iris()
myColumnList = ['sepal_length', 'sepal_width', 'petal_length', 'petal_width']
n = len(myColumnList)
fig = make_subplots(
rows=n, cols=n,
subplot_titles=[f'{i} vs {j}' for i in myColumnList for j in myColumnList],
horizontal_spacing=0.05,
vertical_spacing=0.05
)
for idx, i in enumerate(myColumnList):
for jdx, j in enumerate(myColumnList):
if i != j:
scatter = px.scatter(df, x=i, y=j).data[0]
fig.add_trace(scatter, row=idx+1, col=jdx+1)
else:
# 对角线可放直方图或留空
fig.add_annotation(
xref="x domain", yref="y domain",
x=0.5, y=0.5, showarrow=False,
text=f"<b>{i}</b>", font_size=14,
row=idx+1, col=jdx+1
)
fig.update_layout(height=1200, width=1200, showlegend=False)
fig.show()3. 强制刷新输出缓冲(临时应急方案)
若必须保持单图独立输出,可在循环中显式调用 IPython.display.clear_output(wait=True) 并累积输出,但不推荐用于大量图形(易卡顿):
from IPython.display import clear_output, display
figures = []
for i in myColumnList:
for j in myColumnList:
fig = px.scatter(df, x=i, y=j, title=f'{i} vs {j}')
figures.append(fig)
# 一次性显示全部(依赖浏览器性能)
for fig in figures:
fig.show()
clear_output(wait=True) # 防止瞬时刷屏,但非根本解法? 关键注意事项总结:
- ✅ 永远优先考虑子图整合:既符合数据可视化最佳实践,又彻底规避前端限制;
- ✅ FigureWidget + display() 是动态展示多图的稳健选择,适合教学演示或探索性分析;
- ❌ 避免无节制调用 fig.show() —— 它会持续向输出区追加重量级 HTML,而非“覆盖”;
- ? 若仍遇问题,请升级核心环境:pip install --upgrade plotly jupyter jupyterlab jupyter-server,JupyterLab ≥4.0 / Notebook ≥7.0 对富媒体输出有显著优化;
- ? Binder 等托管环境可能因资源限制更敏感,本地部署通常表现更优。
通过合理选用上述任一方法,即可稳定呈现任意数量的 Plotly 图形,兼顾交互性、性能与专业性。









