绘制覆盖非常慢的箱形图 - 有更快/更好的方法吗?

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)需要很长时间。

以上是关于绘制覆盖非常慢的箱形图 - 有更快/更好的方法吗?的主要内容,如果未能解决你的问题,请参考以下文章

用十进制创建两组之间差距的箱形图

你如何改变熊猫箱形图Y轴的传播?

使用熊猫的箱线图

如何从箱形图数据中删除序列?

在python的箱形图中显示平均值?

利用箱线图过滤数据