在JupyterLab中用for循环调用Plotly绘图未达预期效果
Plotly循环生成重复条形图的问题解决
问题描述
遍历包含4个子列表的列表,通过for循环为每个子列表生成条形图并调用fig.show(),但输出的所有图表完全一致(标题均重复最后一个子列表的内容)。fig.write_html()能生成正确的独立文件,添加time.sleep(2)后显示也恢复正常。
环境信息
matplotlib==3.6.2 matplotlib-inline==0.1.6 plotly==5.7.0 jupyter-events==0.6.3 jupyter_client==8.0.2 jupyter_core==5.2.0 jupyter_server==2.1.0 jupyter_server_terminals==0.4.4 jupyterlab==3.5.3 jupyterlab-pygments==0.2.2 jupyterlab-widgets==3.0.5 jupyterlab_server==2.19.0
问题原因
在Jupyter Lab环境中使用iframe渲染器时,fig.show()是异步执行的。循环执行速度过快,多个渲染请求被合并,最终只渲染了最后一个图表的内容。time.sleep(2)能临时解决是因为给足了异步渲染的时间,但这不是可靠的解决方案。
解决方案
方法1:使用IPython.display.display()替代fig.show()
直接用display()函数渲染每个图表,确保每个图表都被立即处理:
import plotly.graph_objects as go import plotly.io as pio from IPython.display import display pio.renderers.default = "iframe" ys = [ [2, 3, 1], [1, 2, 2], [4, 2, 3], [3, 2, 5] ] for y in ys: title = '-'.join([str(i) for i in y]) fig = go.Figure( data=[go.Bar(y=y)], layout_title_text=title ) display(fig)
方法2:为每个图表指定唯一div_id
在fig.show()中传入唯一的div_id参数,避免渲染冲突:
import plotly.graph_objects as go import plotly.io as pio import uuid pio.renderers.default = "iframe" ys = [ [2, 3, 1], [1, 2, 2], [4, 2, 3], [3, 2, 5] ] for y in ys: title = '-'.join([str(i) for i in y]) fig = go.Figure( data=[go.Bar(y=y)], layout_title_text=title ) fig.show(div_id=str(uuid.uuid4()))
方法3:切换到jupyterlab渲染器
如果你的环境支持,将默认渲染器改为jupyterlab,它的渲染机制更适配Jupyter Lab的异步环境:
pio.renderers.default = "jupyterlab"
之后循环中的fig.show()就能正常显示每个独立图表。
内容的提问来源于stack exchange,提问作者Hong
相关产品推荐
相关产品推荐

