绘制覆盖非常慢的箱形图 - 有更快/更好的方法吗?
Posted
技术标签:
【中文标题】绘制覆盖非常慢的箱形图 - 有更快/更好的方法吗?【英文标题】:Plotly box plots with overlay very slow - is there a faster/better method? 【发布时间】:2022-01-15 20:31:15 【问题描述】:我正在创建一个带有文本覆盖的 Plotly 箱线图。
问题是,虽然我的工作有效,但速度很慢。当我做一个 30 x 16 的盒子时,它需要 30 多分钟才能完成。
import random
import plotly.graph_objects as go
def addSquare(fig, x, y, size, which):
x0 = x - size
x1 = x + size
y0 = y - size
y1 = y + size
if which > 1:
fill = 'LightSkyBlue'
lineCol = 'Blue'
elif which < -1:
fill = 'pink'
lineCol = 'red'
else:
fill = 'Lightgrey'
lineCol = 'grey'
fig.add_shape(
type="rect",
x0=x0, y0=y0,
x1=x1, y1=y1,
fillcolor=fill,
line_color=lineCol,
name=f'Shape_x_y'
)
# Adding a trace with a fill, setting opacity to 0
fig.add_trace(
go.Scatter(
x=[x0,x0,x1,x1,x0],
y=[y0,y1,y1,y0,y0],
fill="toself",
fillcolor=fill,
mode='lines',
name='',
text=f'shape x y<br>size size:.2f<br>cost which:.1f',
opacity=0
)
)
# Draw shape (you won't be able to add a hover text for it)
fig = go.Figure(layout=go.Layout(
title=go.layout.Title(text="A Figure Specified By A Graph Object")
))
for xVal in range(1,12+1):
for yVal in range(1, 15+1):
size = random.uniform(0.1, 0.4) # max 0.4
which = random.uniform(-1.5, 1.5) # > 1 expensive, < 1 cheap
addSquare(fig, xVal, yVal, size, which)
fig.show()
关于如何在保持相同功能的同时加快速度的任何建议?
【问题讨论】:
这段代码 sn-p 创建需要多长时间?在我的笔记本电脑上,这需要几秒钟,如果我将xVal
的范围增加到range(1,31)
同时保持yVal
的范围相同,它仍然只需要大约 10 秒
在我的电脑上,15 和 30,在 VSCode 的 jupyter notebook 中运行需要 30 多秒。您在下面的代码花费了不到一秒钟的时间。
【参考方案1】:
您的代码中有一些冗余:您可能不需要同时使用add_shape
和填充的 go.Scatter 跟踪。您可以单独使用 go.Scatter 实现相同的可视化效果,方法是指定您传递给 add_shape 的相同线条颜色和填充颜色。
例如,在以下代码中,我创建了 30x16 的框。使用 time
模块,以下代码(包括 fig.add_shape 块)采用 30.38765597343445 seconds to render
,同时注释掉该块并使用 go.Scatter 仅将渲染速度显着加快到 1.4587550163269043 seconds
import random
import plotly.graph_objects as go
import time
start_time = time.time()
def addSquare(fig, x, y, size, which):
x0 = x - size
x1 = x + size
y0 = y - size
y1 = y + size
if which > 1:
fill = 'LightSkyBlue'
lineCol = 'Blue'
elif which < -1:
fill = 'pink'
lineCol = 'red'
else:
fill = 'Lightgrey'
lineCol = 'grey'
# fig.add_shape(
# type="rect",
# x0=x0, y0=y0,
# x1=x1, y1=y1,
# fillcolor=fill,
# line_color=lineCol,
# name=f'Shape_x_y'
# )
# Adding a trace with a fill, setting opacity to 0
fig.add_trace(
go.Scatter(
x=[x0,x0,x1,x1,x0],
y=[y0,y1,y1,y0,y0],
fill="toself",
fillcolor=fill,
mode='lines',
name='',
text=f'shape x y<br>size size:.2f<br>cost which:.1f',
line_color=lineCol,
opacity=1,
showlegend=False
)
)
# Draw shape (you won't be able to add a hover text for it)
fig = go.Figure(layout=go.Layout(
title=go.layout.Title(text="A Figure Specified By A Graph Object")
))
for xVal in range(1,30+1):
for yVal in range(1, 15+1):
size = random.uniform(0.1, 0.4) # max 0.4
which = random.uniform(-1.5, 1.5) # > 1 expensive, < 1 cheap
addSquare(fig, xVal, yVal, size, which)
fig.show()
# print(f"(time.time() - start_time) seconds to render")
【讨论】:
如上所述,这比我的代码快得多。显然,绘制形状(而不是 go.scatter)需要很长时间。以上是关于绘制覆盖非常慢的箱形图 - 有更快/更好的方法吗?的主要内容,如果未能解决你的问题,请参考以下文章