Search code examples
pythonplotlydata-visualizationplotly-python

Plotly Sunburst Chart (Python) - 'specs' argument to make_subplots must be a 2D list of dictionaries with dimensions (1 x 1)


I am building a Sunburst chart with python Plotly (version 5.1.0).

I have been following the tutorial here:

https://plotly.com/python/sunburst-charts/#sunburst-chart-with-a-continuous-colorscale

Specifically, I am trying to replicate the last example at the bottom titled 'Sunburst chart with a continuous colorscale'.

When I run it locally, everything works out fine. However when I try to deploy it to my server, the following line of code yields an error.

fig = make_subplots(1, 1, specs=[[{"type": "domain"}, {"type": "domain"}]],)

I get the following ValueError:

The 'specs' argument to make_subplots must be a 2D list of dictionaries with 
dimensions (1 x 1).

Received value of type <class 'list'>: [[{'type': 'domain'}, {'type': 'domain'}]]

I'm not sure why I am receiving this error as I am following the example with the same data structure. Locally it works great. I am not sure if it's an import issue, a library conflict, etc.

Here is my code.

from plotly import graph_objs as go
from plotly.tools import make_subplots
import pandas as pd

df = pd.read_csv('../sunburst_pd.csv')

levels = ['PD', 'State', 'Region'] 
color_columns = ['BP', 'Black']
value_column = 'BP'

def build_hierarchical_dataframe(df, levels, value_column, color_columns=None):
    df_all_trees = pd.DataFrame(columns=['id', 'parent', 'value', 'color'])
    for i, level in enumerate(levels):
        df_tree = pd.DataFrame(columns=['id', 'parent', 'value', 'color'])
        dfg = df.groupby(levels[i:]).sum()
        dfg = dfg.reset_index()
        df_tree['id'] = dfg[level].copy()
        if i < len(levels) - 1:
            df_tree['parent'] = dfg[levels[i+1]].copy()
        else:
            df_tree['parent'] = 'total'
        df_tree['value'] = dfg[value_column]
        df_tree['color'] = dfg[color_columns[0]] / dfg[color_columns[1]]
        df_all_trees = df_all_trees.append(df_tree, ignore_index=True)
    total = pd.Series(dict(id='total', parent='',
                              value=df[value_column].sum(),
                              color=df[color_columns[0]].sum() / 
                              df[color_columns[1]].sum()))
    df_all_trees = df_all_trees.append(total, ignore_index=True)
    return df_all_trees

df_all_trees = build_hierarchical_dataframe(df, levels, value_column, 
    color_columns)
average_score = df['BP'].sum() / df['Black'].sum()

fig = make_subplots(1, 2, specs=[[{"type": "domain"}, {"type": "domain"}]],)

fig.add_trace(go.Sunburst(
    labels=df_all_trees['id'],
    parents=df_all_trees['parent'],
    values=df_all_trees['value'],
    branchvalues='total',
    marker=dict(
        colors=df_all_trees['color'],
        colorscale='RdBu',
        cmid=average_score),
    hovertemplate='<b>%{label} </b> <br> BP: %{value}<br> 
        BP Population: %. {color:.6f}',
    name=''
    ), 1, 1)

fig.add_trace(go.Sunburst(
    labels=df_all_trees['id'],
    parents=df_all_trees['parent'],
    values=df_all_trees['value'],
    branchvalues='total',
    marker=dict(
        colors=df_all_trees['color'],
        colorscale='RdBu',
        cmid=average_score),
    hovertemplate='<b>%{label} </b> <br> BP: %{value}<br> 
        BP Population: %{color:.6f}',
    maxdepth=2
    ), 1, 2)

fig.update_layout(margin=dict(t=10, b=10, r=10, l=10))

fig.show()

Here is a snapshot of my data:

Region. |. State. | PD. |. BP.  |.  Black

South. |.Florida. |. FL. |. 3.  |. 1500
North. | New York. |.NY. |. 7. |.  1275

Any help would be immensely appreciated.


Solution

    • as I understand from comments, your primary goal is to generate a sunburst trace with a continuous colorscale
    • it's much simpler to use plotly express to do core function of building sunburst
    • it's then a simple case of updating the trace with an approach to color required
    • your sample data is quite bare... have added another row to demonstrate this approach

    sample data

    import pandas as pd
    import io
    df = pd.read_csv(io.StringIO("""Region|State|PD|BP|Black
    South. |.Florida. |. FL. |3|1500
    North. | New York. |.NY. |7|1275
    South. |Texas|TX|5|750"""), sep="|", engine="python")
    
    

    sunburst with continuous colorscale

    import plotly.express as px
    import numpy as np
    
    # use plotly express to build the sunburst.  Insert a "Total" column into dataframe so
    # center of sunburst is the total
    fig = px.sunburst(
        df.assign(Total="Total"), path=["Total", "Region", "State"], values="BP"
    )
    
    # want a continuous colorscale.  Simplest way is to use trace built by px and update it...
    fig.update_traces(
        marker={
            "colors": fig.data[0]["values"],
            "colorscale": "RdBu",
            "cmid": np.mean(fig.data[0]["values"]),
        }
    )
    

    output

    enter image description here