Search code examples
pythonplotlyheatmapdendrogram

heatmap and dendrogram (clustermap) error using Plotly


The last example in Plotly's documentation for Dendrograms has an error. When executing this code, I get this error in two locations due to 'extend':

AttributeError: ‘tuple’ object has no attribute ‘extend’

They are produced by these lines: figure.add_traces(heatmap) and figure['data'].extend(dendro_side['data'])

If anyone has run into this problem, please see my solution below! Happy coding!


Solution

  • I have a quick and accurate solution to run the last example code in Plotly's documentation for Dendrograms. Note that I am using Plotly offline in a Jupyter Notebook.

    Figure has methods to add_traces, and these should replace extend.

    The three key lines are :

    figure.add_traces(dendro_side[‘data’])
    figure.add_traces(heatmap)
    plotly.offline.iplot(figure, filename=‘dendrogram_with_heatmap’)
    

    Here is the full example code with my corrections and necessary imports, below:

    # Import Useful Things
    import plotly
    import plotly.plotly as py
    import plotly.graph_objs as go
    import plotly.figure_factory as ff
    from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
    init_notebook_mode(connected=True)    
    plotly.offline.init_notebook_mode(connected=True)
    import plotly.graph_objs as go
    import plotly.figure_factory as ff
    import numpy as np
    from scipy.spatial.distance import pdist, squareform
    
    # Get Data
    data = np.genfromtxt("http://files.figshare.com/2133304/ExpRawData_E_TABM_84_A_AFFY_44.tab",names=True,usecols=tuple(range(1,30)),dtype=float, delimiter="\t")
    data_array = data.view((np.float, len(data.dtype.names)))
    data_array = data_array.transpose()
    labels = data.dtype.names
    
    # Initialize figure by creating upper dendrogram
    figure = ff.create_dendrogram(data_array, orientation='bottom', labels=labels)
    for i in range(len(figure['data'])):
        figure['data'][i]['yaxis'] = 'y2'
    
    # Create Side Dendrogram
    dendro_side = ff.create_dendrogram(data_array, orientation='right')
    for i in range(len(dendro_side['data'])):
        dendro_side['data'][i]['xaxis'] = 'x2'
    
    # Add Side Dendrogram Data to Figure
    figure.add_traces(dendro_side['data'])
    
    # Create Heatmap
    dendro_leaves = dendro_side['layout']['yaxis']['ticktext']
    dendro_leaves = list(map(int, dendro_leaves))
    data_dist = pdist(data_array)
    heat_data = squareform(data_dist)
    heat_data = heat_data[dendro_leaves,:]
    heat_data = heat_data[:,dendro_leaves]
    
    heatmap = [
    go.Heatmap(
        x = dendro_leaves,
        y = dendro_leaves,
        z = heat_data,
        colorscale = 'Blues'
      )
    ]
    
    heatmap[0]['x'] = figure['layout']['xaxis']['tickvals']
    heatmap[0]['y'] = dendro_side['layout']['yaxis']['tickvals']
    
    figure.add_traces(heatmap)
    
    # Edit Layout
    figure['layout'].update({'width':800, 'height':800,
                         'showlegend':False, 'hovermode': 'closest',
                         })
    # Edit xaxis
    figure['layout']['xaxis'].update({'domain': [.15, 1],
                                  'mirror': False,
                                  'showgrid': False,
                                  'showline': False,
                                  'zeroline': False,
                                  'ticks':""})
    # Edit xaxis2
    figure['layout'].update({'xaxis2': {'domain': [0, .15],
                                   'mirror': False,
                                   'showgrid': False,
                                   'showline': False,
                                   'zeroline': False,
                                   'showticklabels': False,
                                   'ticks':""}})
    
    # Edit yaxis
    figure['layout']['yaxis'].update({'domain': [0, .85],
                                  'mirror': False,
                                  'showgrid': False,
                                  'showline': False,
                                  'zeroline': False,
                                  'showticklabels': False,
                                  'ticks': ""})
    # Edit yaxis2
    figure['layout'].update({'yaxis2':{'domain':[.825, .975],
                                   'mirror': False,
                                   'showgrid': False,
                                   'showline': False,
                                   'zeroline': False,
                                   'showticklabels': False,
                                   'ticks':""}})
    # Plot using Plotly Offline
    plotly.offline.iplot(figure, filename='dendrogram_with_heatmap')
    

    This outputs:

    Heatmap with Dendrogram in Plotly