Black Lives Matter. Please consider donating to Black Girls Code today.

Bar Chart - Bars have multiple segments - how to remove segment lines

I have a bar chart, and on the individual bars, I see little segments that I assume means I have a stacked bar chart.

My data is city, month, and sales. My x values are city, and my y values are sales. I do not show month on the chart at all.

There are 7 segments in each city’s bar, so I think these are the monthly sales for that city.

How can I get display just the total sales for the ciy and not the individual segments?

I know I can create another dataframe, drop month, and groupby city, But I am trying to limit the number of dataframes I have.

IS there a Plotly or Dash setting to do this? Or if I need to do it in the dataframe, is there a way to create a temporary, i.e.non memory, way, in Pandas?

Thanks

You can use a histogram for this, with the histfunc='sum' parameter. For example

import plotly.express as px
df = px.data.tips()
fig = px.histogram(df, x='sex', y='tip', histfunc='sum')
# uncomment line below to check that it's the same value as the bar chart, minus segments
# fig = px.bar(df, x='sex', y='tip')
fig.show()

Thanks for the reply.

I can’t seem to get it to work.

I did not want to cloud the issue, but I am using a callback to hover over a state on a state bar chart and then pass the state value to the city chart. Here is the callback and related code that does work and return a city bar chart of cities in the state selected:

@app.callback(Output("city-bar", "figure"),
        [Input("state-bar", "hoverData")])
def on_hover(hover_data):
    if not hover_data:
        return dash.no_update

    state = hover_data["points"][0]["x"]
    sales = df.loc[df.state == state]

    return go.Figure(
                    [go.Bar(
                        x=sales.city,
                        y=sales.sales,
                        width=.2,
                        name="City"
                        )],
                    go.Layout(
                        xaxis={'title': 'City'},
                        yaxis={'title': 'Sales'},
                        margin=dict(
                            b=50, #bottom margin 40px
                            l=50, #left margin 40px
                            r=50, #right margin 20px
                            t=50, #top margin 20px
                        ),
                        bargap=.1
                ))

Then I use this code in the following section:

        html.Div([
            dcc.Graph(id="city-bar",
                style={'height': 250, "border-style": "solid", "border-width": 1, "border-color": "lightgrey"}
                )
        ]

I tried to substitute the appropriate code, like “histogram”, in the above and it didn’t work. I also tried using the histogram examples from the Plotly not plotly express and that didn’t work.

I think the problem is that I cannot determine where the line fig.show() should go in my callback scenario. Does it go in the call back and the def section or does it go into the dcc.graph section?

Thanks again for posting.

I found a solution by creating a state city sales data frame and thus eliminating the month column altogether. I am worried though that I now have a data frame for each of the four charts on my dashboard.

Is there some layout or formatting option to total by city and not show each month segment?

Or am I stuck with having a data frame per chart?

Thanks for any help,

James

The callback needs to return a figure object (created by go.Figure or by a plotly express function), so you don’t need to call fig.show() (the Dash server takes care of the rendering). For generating the figure, you can either replace go.Bar by go.Histogram in your snippet, or call px.histogram to generate directly the figure.

Solution 1

@app.callback(Output("city-bar", "figure"),
        [Input("state-bar", "hoverData")])
def on_hover(hover_data):
    if not hover_data:
        return dash.no_update

    state = hover_data["points"][0]["x"]
    sales = df.loc[df.state == state]

    return go.Figure(
                    [go.Histogram(
                        x=sales.city,
                        y=sales.sales,
                        width=.2,
                        histfunc='sum',
                        name="City"
                        )],
                    layout=go.Layout(
                        xaxis={'title': 'City'},
                        yaxis={'title': 'Sales'},
                        margin=dict(
                            b=50, #bottom margin 40px
                            l=50, #left margin 40px
                            r=50, #right margin 20px
                            t=50, #top margin 20px
                        ),
                        bargap=.1
                ))

Solution 2

@app.callback(Output("city-bar", "figure"),
        [Input("state-bar", "hoverData")])
def on_hover(hover_data):
    if not hover_data:
        return dash.no_update

    state = hover_data["points"][0]["x"]
    sales = df.loc[df.state == state]

    fig = px.histogram(sales, 
                                 x='city',
                                 y='sales',
                                 histfunc='sum',
                                 title='City')
   fig.update_layout(
                    dict(
                        xaxis={'title': 'City'},
                        yaxis={'title': 'Sales'},
                        margin=dict(
                            b=50, #bottom margin 40px
                            l=50, #left margin 40px
                            r=50, #right margin 20px
                            t=50, #top margin 20px
                        ),
                        bargap=.1
                ))
    return fig

(I did not execute this code since I did not have your data, I hope there is no typo)

For a future question, don’t hesitate to post from the start a minimal example of code, it will help us giving a relevant answer.

Emmanuelle,

Thanks for sticking with this.

Your code does work. The one issue I have is how to control the size of the bars or bins. Some states have many cities, and the bars or bins look good. Other states only have a few bars or bins, and these are very wide and do not look good. I have tried several of the parameters in the reference manual, but none seem to adjust the bar widths or bin sizes for states with just 2 or 3 cities.

Again, thanks for your help on this.

James