绘制热图的浏览器渲染速度较慢

人气:856 发布:2022-10-16 标签: performance python plotly dataframe heatmap

问题描述

我呈现了一个从0到6的212行x64列的整数df(Final_Df),作为(无注释的)带注释的热图。我使用fig.write_html()中的一个文件在我的浏览器(Microsoft EDGE)中执行此操作。最终的热图在我的浏览器中呈现得非常慢,以至于我收到"页面未响应"警告,任何放大/缩小图形的操作也都非常慢。考虑到df不是那么大,这很令人惊讶。

有谁能建议为什么会出现这种情况,以及如何加快速度?

谢谢, TIM

def discrete_colorscale(bvals, colors):
    #https://chart-studio.plotly.com/~empet/15229/heatmap-with-a-discrete-colorscale/#/
    """
    bvals - list of values bounding intervals/ranges of interest
    colors - list of rgb or hex colorcodes for values in [bvals[k], bvals[k+1]],0<=k < len(bvals)-1
    returns the plotly  discrete colorscale
    """
    if len(bvals) != len(colors)+1:
        raise ValueError('len(boundary values) should be equal to  len(colors)+1')
    bvals = sorted(bvals)     
    nvals = [(v-bvals[0])/(bvals[-1]-bvals[0]) for v in bvals]  #normalized values
    
    dcolorscale = [] #discrete colorscale
    for k in range(len(colors)):
        dcolorscale.extend([[nvals[k], colors[k]], [nvals[k+1], colors[k]]])
    return dcolorscale


#final_df is a 212 row x 64 col df of ints ranging from 0 to 6
#cell_df is an empty 212x64 df of empty strings to remove cell labelling behaviour
cell_df = final_df.applymap(lambda x: annot_map.get(x, x)) 
cell_labels = cell_df.values.tolist()
bvals = [0,1,2,3,4,5,6,7]

colors_map = ['rgb(244,244,255)', #whiteish 
              'rgb(255, 128, 0)', #orange 
              'rgb(255,0,0)', #red 
              'rgb(0, 0, 255)', #blue 
              'rgb(128, 128, 128)', #grey 
              'rgb(0, 255, 0)', #green 
              'rgb(192, 192, 192)'] #light grey

dcolorsc = discrete_colorscale(bvals, colors_map)
bvals = np.array(bvals)
tickvals = [np.mean(bvals[k:k+2]) for k in range(len(bvals)-1)]
ticktext  = ['param 1', 
             'param 2',
             'param 3',
             'param 4',
             'param 5',
             'param 6',
             'param 7']

fig_df = ff.create_annotated_heatmap(final_df.values.tolist(), 
                                      x= list(final_df.columns), 
                                      y=list(final_df.index), 
                                      annotation_text  = cell_labels, 
                                      colorscale=dcolorsc,
                                      colorbar = dict(thickness=25, 
                                                      tickvals=tickvals, 
                                                      ticktext=ticktext),
                                      showscale  = True,
                                      zmin=0, zmax=7,
                                      ygap = 1,
                                      xgap = 1,
                                      )
fig_df.update_layout(
    xaxis={'title' : 'ID 1'},
    yaxis = {'title' : 'ID 2'},
    yaxis_nticks = len(final_df.index),
    xaxis_nticks = len(final_df.columns)
    )

fig_df.write_html(results_file_df)

推荐答案

我怀疑绘图呈现批注的成本非常高。可能的情况是,即使您向annotation_text参数传递了一个212x64空字符串数组,仍然需要逐一检查它们,以确定没有要添加的批注。

我用从0到6的随机整数创建了一个212x64数组,在我的浏览器中呈现它的速度也非常慢,并且我收到了与您相同的页面没有响应&q;警告。

当我使用go.heatmap时,我能够获得似乎与ff.create_annotated_heatmap相同的绘图,这将执行时间从5-6秒缩短到0.66秒,并且它在浏览器中的响应速度也快得多。

这似乎比创建带注释的热图而不使用注释更简单(您需要ff.create_注解_heatmap而不是go.heatmap有什么特殊原因吗?)

import numpy as np
import pandas as pd
import plotly.figure_factory as ff
import plotly.graph_objects as go

import time
start_time = time.time()

def discrete_colorscale(bvals, colors):
    #https://chart-studio.plotly.com/~empet/15229/heatmap-with-a-discrete-colorscale/#/
    """
    bvals - list of values bounding intervals/ranges of interest
    colors - list of rgb or hex colorcodes for values in [bvals[k], bvals[k+1]],0<=k < len(bvals)-1
    returns the plotly  discrete colorscale
    """
    if len(bvals) != len(colors)+1:
        raise ValueError('len(boundary values) should be equal to  len(colors)+1')
    bvals = sorted(bvals)     
    nvals = [(v-bvals[0])/(bvals[-1]-bvals[0]) for v in bvals]  #normalized values
    
    dcolorscale = [] #discrete colorscale
    for k in range(len(colors)):
        dcolorscale.extend([[nvals[k], colors[k]], [nvals[k+1], colors[k]]])
    return dcolorscale


#final_df is a 212 row x 64 col df of ints ranging from 0 to 6
#cell_df is an empty 212x64 df of empty strings to remove cell labelling behaviour

## recreate your dfs

np.random.seed(42)
final_df = pd.DataFrame(np.random.randint(0,6,size=(212, 64)), columns=list(range(64)))

# cell_df = final_df.applymap(lambda x: annot_map.get(x, x)) 
cell_df = pd.DataFrame(np.array(['']*212*64).reshape(212,64), columns=list(range(64)))
cell_labels = cell_df.values.tolist()
bvals = [0,1,2,3,4,5,6,7]

colors_map = ['rgb(244,244,255)', #whiteish 
              'rgb(255, 128, 0)', #orange 
              'rgb(255,0,0)', #red 
              'rgb(0, 0, 255)', #blue 
              'rgb(128, 128, 128)', #grey 
              'rgb(0, 255, 0)', #green 
              'rgb(192, 192, 192)'] #light grey

dcolorsc = discrete_colorscale(bvals, colors_map)
bvals = np.array(bvals)
tickvals = [np.mean(bvals[k:k+2]) for k in range(len(bvals)-1)]
ticktext  = ['param 1', 
             'param 2',
             'param 3',
             'param 4',
             'param 5',
             'param 6',
             'param 7']

# fig_df = ff.create_annotated_heatmap(final_df.values.tolist(), 
#                                       x= list(final_df.columns), 
#                                       y=list(final_df.index), 
#                                       annotation_text  = cell_labels, 
#                                       colorscale=dcolorsc,
#                                       colorbar = dict(thickness=25, 
#                                                       tickvals=tickvals, 
#                                                       ticktext=ticktext),
#                                       showscale  = True,
#                                       zmin=0, zmax=7,
#                                       ygap = 1,
#                                       xgap = 1,
#                                       )

fig_df = go.Figure([go.Heatmap(
    z=final_df,
    colorscale=dcolorsc,
    colorbar=dict(
        thickness=25, 
        tickvals=tickvals, 
        ticktext=ticktext),
    showscale=True,
    zmin=0, zmax=7,
    ygap=1,
    xgap=1,
    )
])

fig_df.update_layout(
    xaxis={'title' : 'ID 1'},
    yaxis = {'title' : 'ID 2'},
    yaxis_nticks = len(final_df.index),
    xaxis_nticks = len(final_df.columns)
    )

fig_df.show()

print(f"Program executed in {time.time() - start_time} seconds")

## original code with figure_factory annotated heatmap: Program executed in 5.351915121078491 seconds
## modified code with graph_objects heatmap: Program executed in 0.6627509593963623 seconds
# fig_df.write_html(results_file_df)

806