1

I am new to Plotly and fascinated by its interactive features. I have three pandas dataframes of electricity generation mix of three countries, which looks like this: enter image description here

I have been able to create an interactive bar chart using Plotly for electricity generation mix based on df1 using

import plotly.express as px fig=px.bar(df1, title="Electricity generation mix of Germany in TWh (2000-2019)", color_discrete_sequence=colors) fig

enter image description here

I intend to add a button or dropdown to this bar chart, where I can select countries based on each data frame (df1,df2 and df3). What would be the best approach to do it? Should I rather have the data of all three countries in one dataframe?

1
  • Check out my two posts (one and two) for some general pointers. If you're still stuck, you're more than welcome to ask me for help in your specific case Commented Jan 13, 2021 at 22:37

1 Answer 1

4

The easiest way to do this is to use the graph objects library and iterate through your data with the "add_trace" method of a Plotly figure.

import pandas as pd
import plotly.graph_objects as go

#Dummy data
df_germany = pd.DataFrame({'Fuels':[2010,2011],'Coal':[200,250],'Gas':[400,500]})
df_poland = pd.DataFrame({'Fuels':[2010,2011],'Coal':[500,150],'Gas':[600,100]})
df_spain = pd.DataFrame({'Fuels':[2010,2011],'Coal':[700,260],'Gas':[900,400]})

#put dataframes into object for easy access:
df_dict = {'Germany': df_germany, 
           'Poland': df_poland, 
           'Spain': df_spain}

#create a figure from the graph objects (not plotly express) library
fig = go.Figure()

buttons = []
i = 0

#iterate through dataframes in dict
for country, df in df_dict.items():
    #iterate through columns in dataframe (not including the year column)
    for column in df.drop(columns=['Fuels']):
        #add a bar trace to the figure for the country we are on
        fig.add_trace(go.Bar(
                          name = column,
                          #x axis is "fuels" where dates are stored as per example
                          x = df.Fuels.to_list(),
                          #y axis is the data for the column we are on
                          y = df[column].to_list(),
                          #setting only the first country to be visible as default
                          visible = (i==0)
                        )
                     )
        
    #args is a list of booleans that tells the buttons which trace to show on click
    args = [False] * len(df_dict)
    args[i] = True
    
    #create a button object for the country we are on
    button = dict(label = country,
                  method = "update",
                  args=[{"visible": args}])
    
    #add the button to our list of buttons
    buttons.append(button)
    
    #i is an iterable used to tell our "args" list which value to set to True
    i+=1
        
fig.update_layout(
    updatemenus=[
        dict(
        #change this to "buttons" for individual buttons
        type="dropdown",
        #this can be "left" or "right" as you like
        direction="down",
        #(1,1) refers to the top right corner of the plot
        x = 1,
        y = 1,
        #the list of buttons we created earlier
        buttons = buttons)
    ],
    #stacked bar chart specified here
    barmode = "stack",
    #so the x axis increments once per year
    xaxis = dict(dtick = 1))

fig.show()
        

Should yield: Plotly stacked bar with dropdown example

Sign up to request clarification or add additional context in comments.

4 Comments

Could you specify how I can also define color sequence, e.g. black color for Coal and grey for Gas?
@HimalayaBirShrestha Regarding your comment, didn't you ask a very similar question yesterday?
@vestland yes, i did. But it's a different case since plotly.express is different as compared to plotly.graph_objects. I tried to loop through the colors in fig.add_trace(go.Bar(marker_color=color). I was able to get the desired color for the first option but as soon as I selected the second or third option from the dropdown or the button, the color got distorted. Therefore, I wanted to ask what would be the appropriate way to define color sequence in this case.
add "marker = dict(color = ["colour for column we are on"] * len(df.Fuels.to_list())" to the for loop inside of the "Bar" object

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.