Search code examples
pythonplotlyplotly-dashjupyterdash

Plotly JupyterDash is not removing irrelevant columns when applying categoryorder sort to measure with a negative value


I'm trying to sort the axis of my chart based on the values in the "sales" column. Once I apply fig.update_layout(yaxis={'categoryorder':'total descending'}) to my figure, the chart no longer removes irrelevant rows when filtering the dataframe by selecting the "099" value for the RadioItems callback option.

code to recreate issue:

import pandas as pd

from plotly import tools
import plotly.express as px
import plotly.graph_objects as go

import dash
import dash_core_components as dcc
import dash_html_components as html
from jupyter_dash import JupyterDash
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output


data = {'name': {0: 'G P', 1: 'D L', 2: 'T B', 3: 'N A', 4: 'P O', 5: 'Ho A'},
 'team': {0: '099', 1: '099', 2: '073', 3: '073', 4: '073', 5: '099'},
 'sales': {0: 88946, 1: 8123, 2: 6911, 3: 74796, 4: 8532, 5: -31289}
       }

df1 = pd.DataFrame.from_dict(data)

app = JupyterDash(external_stylesheets=[dbc.themes.SLATE])
template = 'plotly_dark'

controls = dbc.Card(
        [
        dbc.FormGroup(
            [
            dbc.Label("Teams"),
             dcc.RadioItems(
                id='slm-radio',
                options=[{'label': 'All', 'value': 'All'}] + 
                 [{'label': k, 'value': k} for k in df1['team'].unique()],
                value='All',
        
                        ),
            ],
                    )
        ]
)

app.layout = dbc.Container(
    [
        dbc.Row([
            dbc.Col([controls],xs = 4),
            dbc.Col([
                dbc.Row([
                    dbc.Col(dcc.Graph(id="sales_graph")),
                ])
            ]),
        ]),
        html.Br(),
    ],
    fluid=True,
)

@app.callback(
    Output("sales_graph", "figure"),
    [
        Input("slm-radio", "value")
    ],
)
def history_graph(team):
    dataset  = df1
        
    if not team == 'All':
        dataset = dataset[dataset['team']==team]
    else:
        dataset = dataset    
    
    v_cat = dataset['name']
    x_val = dataset['sales']

    fig = go.Figure(go.Bar(
        x=x_val,
        y=v_cat,
        marker_color="#ff0000",
        orientation='h',
        width=0.25
        ))
    fig.update_layout(template='plotly_dark')
    fig.update_layout(yaxis={'categoryorder':'total descending'})    

    return fig

app.run_server(mode='inline', port = 8009)

The desired results is to remove the N A, P O, and T B columns when '099' is selected

I get the desired results if:

  1. the value for 'Ho A' is changed to positive
  2. sorting the axis is removed
  3. if graph is rendered using plotly locally without dash

Solution

  • I was able to work around this issue by computing the ranking independently of the graphing step and placing the rankings into a series, rankings. I then passed the ranked series to

    fig.update_layout(yaxis={'categoryorder':'array', 'categoryarray':rankings['team_rank']})