Search code examples
pandasplotlybar-chartplotly-pythonstacked-chart

Creating ONE stacked bar beside ONE normal bar in plotly?


I have this series called 'CountryCounts' which is the result of calling .value_counts() on my original dataframe's 'Country' column OGdf['Country'].

United States           1234
United Kingdom           332
Canada                   111
France                    61
Australia                 55
                        ... 
Israel                     1
Bahamas                    1
Romania                    1
Greece                     1
United Arab Emirates       1
Name: Country, Length: 63, dtype: int64

What I want to do is create a plotly bar plot in which the first row (in this case the United States - 1234) is plotted as its own bar.

Then every other row combined is plotted next to it as a stacked bar (total length would be the sum of the others) but with hover info for each individual row (so that you can still see United Kingdom as its own color within that bar, Canada, etc.)

I have created a short function to separate out the remaining entries until they are equivalent to the first one:

def find_next_series_equivalent(series):
  primary = series[0]
  if series[1:-1].sum() > primary:
    i = 2
    while series[1:i].sum() < primary:
      i += 1
    return series[1:i]
  else:
    return series[1:-1]

I have tried this by doing histogram:

fig = px.histogram(OGdf, x='Country', barmode='stack')

And barplot:

first_entry = OGdf['Country'].value_counts()[0]
fig = px.bar(y = [first_entry.index], x= [first_entry.values], orientation='h')
fig.update_xaxes(title='# From Country')
fig.update_yaxes(title='Country')

othersdict = find_next_series_equivalent(OGdf['Country'].value_counts()).to_dict()
   

othersBar = go.Bar(
     y = othersdict.index,
     x = othersdict.values)

fig.add_trace(othersBar, row=1, col=1)

fig.update_layout(barmode='stack')

Neither of which accomplish my goals. Help is much appreciated. Thanks in advance :)

(btw I'm using plotly express and my pandas plotting backend is set to plotly)


Solution

    • it's simple if you create figure as you describe it. xaxis is one of two values
    • rest is then setting parameters to plotly express bar
    • have hidden legend, you can display if you want but will probably be too long with 60+ countries
    • used your sample data from value_counts()
    import plotly.express as px
    import io
    import pandas as pd
    import numpy as np
    
    df = pd.read_csv(io.StringIO("""United States           1234
    United Kingdom           332
    Canada                   111
    France                    61
    Australia                 55
    Israel                     1
    Bahamas                    1
    Romania                    1
    Greece                     1
    United Arab Emirates       1"""), sep="\s\s+", engine="python", header=None).rename(columns={0:"Country",1:"Count"})
    
    fig = px.bar(df, x=np.where(df["Country"].eq("United States"), "United States", "Other"), y="Count", 
           hover_data=["Country"], color="Country")
    
    # if legend is not wanted...
    fig = fig.update_layout(showlegend=False)
    fig
    

    enter image description here