title: overlay bar chart with call back
body: <p>I do have 3 data frames df1, df2 and df3. I want to create an overlay bar chart that update information graph when a choose a uear in the dropdown that.</p>
  <p><a href="https://i.stack.imgur.com/Chidf.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/Chidf.png" alt="enter image description here" /></a></p>
  <p>data frame 1 look like this:</p>
  <pre class="lang-py prettyprint-override"><code>data = {'years': [2022, 2022, 2022, 2023, 2023, 2023, '.', '.', '.',2028, 2028, 2028], 
          'contract': ['ppa', 'oa', 'cr', 'ppa', 'oa', 'cr', '.', '.', '.', 'ppa', 'oa', 'cr'], 
          'quarters': ['Q1', 'Q1', 'Q1', 'Q2', 'Q2', 'Q2', '.', '.', '.', 'Q4', 'Q4', 'Q4'], 
          'hedge': [340, 300, 550, 444, 390, 130, '.', '.', '.', 100, 102, 155]}
  df1 = pd.DataFrame(data=data)
  </code></pre>
  <p>data frame 2 look like this:</p>
  <pre class="lang-py prettyprint-override"><code>data = {'years': [2022, 2022, 2022, 2022, 2023, 2023, 2023, 2023, '.' , '.' , '.' ,2028, 2028, 2028, 2028], 
          'quarters': ['Q1', 'Q2', 'Q3', 'Q4', 'Q1', 'Q2', 'Q3', 'Q4', '.', '.', '.', 'Q1', 'Q2', 'Q3', 'Q4'], 
          'prod': [1030, 1050, 1000, 2500, 389, 230, 240, 220, '.', '.', '.', 450, 340, 140, 155]}
  df2 = pd.DataFrame(data=data)
  </code></pre>
  <p>data frame 3 look like this:</p>
  <pre class="lang-py prettyprint-override"><code>data = {'years': [2022, 2022, 2022, 2022, 2023, 2023, 2023, 2023, '.' , '.' , '.' ,2028, 2028, 2028, 2028], 
          'quarters': ['Q1', 'Q2', 'Q3', 'Q4', 'Q1', 'Q2', 'Q3', 'Q4', '.', '.', '.', 'Q1', 'Q2', 'Q3', 'Q4'], 
          'hcr': [99.29%, 99.14%, 99.27%, 99.11%, 38%, 30%, 49%, 55%, '.', '.', '.', 50%, 34%, 14%, 5%]}
  df3 = pd.DataFrame(data=data)
  </code></pre>
  <p>I created a dropdown that contains years dropdown from 2022 to 2028:</p>
  <pre class="lang-py prettyprint-override"><code>list_quarters =['Q1', 'Q2', 'Q3', 'Q4']
  quarters = pd.DataFrame(list_quarters, columns=['quarters'])
  
  list_years=[2022, 2023, 2024, 2025, 2026, 2027, 2028]
  years= pd.DataFrame(list_years, columns=['years'])
  
  year_count = []
  for year in years['years'].unique():
      year_count.append({'label':str(year),'value':year})
  
  dcc.Dropdown(id='drop_year_h_q', options=year_count, value=years['years'].min(), 
                   style=dict(width='40%', verticalAlign=&quot;left&quot;, display='inline-block'))
  </code></pre>
  <p>I created graph annotations that display the percentage:</p>
  <pre class="lang-py prettyprint-override"><code>annotations = [dict(
              x=xi,
              y=yi,
              text=str(zi),
              xanchor='auto',
              yanchor='bottom',
              showarrow=False,
              align='center', 
              font=dict(size=8),
          ) for xi, yi, zi in zip(quarters['quarters'],
  df2['prod'],
  df3['hcr'])]
  </code></pre>
  <p>My application look like this:</p>
  <pre class="lang-py prettyprint-override"><code>app=html.Div(
      
      children=[
      html.H2(
          children=&quot;&quot;,
          style={
              &quot;font-size&quot;: 14,
              &quot;margin-bottom&quot;: &quot;0em&quot;,
              &quot;margin-top&quot;: &quot;1em&quot;,
              },
          ),
      
      #Dropdown
      dcc.Dropdown(id='drop_year', options=year_count, value=years['years'].min(), 
                   style=dict(width='40%', verticalAlign=&quot;left&quot;, display='inline-block')),
      #Hedge per quarter
      dcc.Graph(id='hedge_type',
                figure = {'data':[
   
                   go.Bar(
                        name='HCR', 
                        x=quarters['quarters'], 
                        y=df3['hcr'],
                        opacity=0,
                        ), 
                    go.Bar(
                        name='PPA',
                        x=quarters['quarters'],
                        y=df1.loc[df1['contract']=='ppa', 'hedge'],
                        opacity=1,
                        ),
                    go.Bar(
                        name='OA',
                        x=quarters['quarters'],
                        y=df1.loc[df1['contract']=='oa', 'hedge'],
                        opacity=0.4,
                        ),
                    go.Bar(
                        name='CR',
                        x=quarters['quarters'],
                        y=df1.loc[df1['type_contract']=='cr', 'hedge'],
                        opacity=0.25,
                        ),
   
                    go.Bar(
                        name='Production', 
                        x=quarters['quarters'],
                        y=df2['prod'],
                        opacity=0.1
                       ),
                    ],
                    'layout':go.Layout(title='',
                                       annotations=annotations,
                                       xaxis=dict(title='quarter'), 
                                       yaxis=dict(title ='GWh', side='left'),
                                       barmode='overlay',
                                       showlegend=True,
                                       ),
                    }, 
                style={'width': '100%', 'display': 'inline-block', 'vertical-align': 'top'},
                ),
          
          ],
      )
  </code></pre>
  <p>I tried the following callback but, it seems to not working.</p>
  <pre class="lang-py prettyprint-override"><code>@app.callback(Output('hedge_type', 'figure'),
                [Input('drop_year', 'value')])
  
  def update_figure(selected_year):
      filtered_df1 = df1[df1['years'] == selected_year]
      filtered_df2 = df2[df2['years'] == selected_year]
      traces_ppa = []
      traces_oa = []
      traces_cr = []
      for quarter in filtered_df1['quarters'].unique():
          df_h = filtered_df1[filtered_df1['quarters'] == quarter]
          traces_ppa.append(go.Bar(
              name='PPA',
              x=quarters['quarters'],
              y=df_h.loc[df_h['contract']=='ppa', 'hedge']),
              opacity=1,
              ),
          traces_oa.append(go.Bar(
              name='OA',
              x=quarters['quarters'],
              y=df_h.loc[df_h['contract']=='oa', 'hedge']),
              opacity=0.4
              ),
          traces_cr.append(go.Bar(
              name='CR',
              x=quarters['quarters'],
              y=df_h.loc[df_h['contract']=='cr', 'hedge']),
              opacity=0.25,
              ),
  
      for quarter in filtered_df2['quarters'].unique():
          df_p = filtered_df2[filtered_df2['quarters'] == quarter]
          traces_p = []
          traces_p.append(go.Bar(
              name='Production',
              x=quarters['quarters'],
              y=df_p['prod'],
              marker=dict(color=colors['l_green']),
              opacity=0.1,
              
              ))
              
      return {
          'data': (traces_ppa, traces_oa, traces_cr, traces_p),
          'layout': go.Layout(title='',
              annotations=annotations,
              xaxis=dict(gridcolor=colors['grid'], title='quarter', dtick=1),
              yaxis=dict(gridcolor=colors['grid'], title= 'GWh', side='left'),
              showlegend = True,
              barmode = &quot;overlay&quot;,
              paper_bgcolor = colors[&quot;background1&quot;],
              plot_bgcolor= colors[&quot;background1&quot;],
              font=dict(color=colors[&quot;text&quot;], size=PLOTS_FONT_SIZE),
              legend=dict(orientation=&quot;h&quot;, yanchor=&quot;bottom&quot;, y=1.02, xanchor=&quot;right&quot;, x=1),
              hovermode=&quot;x unified&quot;,
          )
      }
  
  </code></pre>
  <p>Could someone help me to properly write a callback. for an overlay bar chart. The final graph should look like the following picture.<br />
  <a href="https://i.stack.imgur.com/eEi5x.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/eEi5x.png" alt="enter image description here" /></a></p>
  <p>This is the complete data sets as well as the code</p>
  <pre class="lang-py prettyprint-override"><code>import plotly.graph_objs as go
  import dash
  import dash_core_components as dcc
  import dash_html_components as html
  from dash.dependencies import Output, Input
  import plotly.io as pio
  
  ###df1
  import pandas as pd
  data = {'years': [2022,2022,2022, 2022,2022,2022, 2022,2022,2022, 2022,2022,2022, 2023,2023,2023, 2023,2023,2023, 2023,2023,2023, 2023, 2023,2023, 2024,2024,2024, 2024,2024,2024, 2024,2024,2024, 2024,2024,2024, 2025,2025,2025, 2025,2025,2025, 2025,2025,2025, 2025,2025,2025, 2026,2026,2026, 2026,2026,2026, 2026,2026,2026, 2026,2026,2026, 2027,2027,2027,2027,2027,2027, 2027,2027,2027, 2027,2027,2027], 
          'contract': ['ppa','oa','cr', 'ppa','oa','cr', 'ppa','oa','cr', 'ppa','oa','cr', 'ppa','oa','cr', 'ppa','oa','cr', 'ppa','oa', 'cr', 'ppa','oa','cr', 'ppa','oa','cr', 'ppa','oa','cr', 'ppa', 'oa','cr', 'ppa','oa','cr', 'ppa','oa','cr', 'ppa','oa','cr','ppa','oa','cr', 'ppa','oa','cr', 'ppa','oa','cr', 'ppa','oa', 'cr', 'ppa','oa','cr', 'ppa','oa','cr', 'ppa','oa','cr', 'ppa','oa','cr', 'ppa','oa','cr', 'ppa','oa','cr'], 
          'quarters': ['Q1','Q1','Q1', 'Q2','Q2','Q2', 'Q3','Q3','Q3', 'Q4', 'Q4','Q4', 'Q1','Q1','Q1', 'Q2','Q2','Q2', 'Q3','Q3','Q3', 'Q4','Q4','Q4', 'Q1','Q1','Q1', 'Q2','Q2','Q2', 'Q3','Q3','Q3', 'Q4','Q4','Q4', 'Q1','Q1','Q1', 'Q2','Q2','Q2', 'Q3','Q3','Q3', 'Q4','Q4','Q4', 'Q1','Q1','Q1', 'Q2','Q2','Q2', 'Q3','Q3','Q3', 'Q4','Q4','Q4', 'Q1','Q1','Q1', 'Q2','Q2','Q2', 'Q3','Q3','Q3', 'Q4','Q4', 'Q4'], 
          'hedge': [340, 300, 550, 444, 390, 130, 200, 340, 224, 100, 102, 155, 340, 300, 550, 444, 390, 130, 200, 340, 224, 100, 102, 155, 340, 300, 550, 444, 390, 130, 200, 340, 224, 100, 102, 155, 340, 300, 550, 444, 390, 130, 200, 340, 224, 100, 102, 155,
          340, 300, 550, 444, 390, 130, 200, 340, 224, 100, 102, 155,
          340, 300, 550, 444, 390, 130, 200, 340, 224, 100, 102, 155,]}
  df1 = pd.DataFrame(data=data)
  ###df2
  data = {'years': [2022,2022,2022,2022, 2023,2023,2023,2023, 2024,2024,2024,2024, 2025,2025,2025,2025, 
                    2026,2026,2026,2026, 2027,2027,2027,2027], 
          'quarters': ['Q1','Q2','Q3','Q4', 'Q1','Q2','Q3','Q4', 'Q1','Q2','Q3','Q4', 
                       'Q1','Q2','Q3','Q4', 'Q1','Q2','Q3','Q4', 'Q1','Q2','Q3','Q4'], 
          'prod': [703.9,483.4,425,727, 770,548,448,830, 886,625,951,1027, 767,697,1091,1161, 
                   885,805,1210,1340, 1108,1118,1445,1458]}
  df2 = pd.DataFrame(data=data)
  ###df3
  data = {'years': [2022,2022,2022,2022, 2023,2023,2023,2023, 2024,2024,2024,2024, 
                    2025,2025,2025,2025, 2026,2026,2026,2026, 2027,2027,2027,2027], 
          'quarters': ['Q1','Q2','Q3','Q4', 'Q1','Q2','Q3','Q4', 'Q1','Q2','Q3','Q4', 
                       'Q1','Q2','Q3','Q4', 'Q1','Q2','Q3','Q4', 'Q1','Q2','Q3','Q4'], 
          'hcr': ['99.29%','99.14%','99.27%','99.11%', '38%','30%','49%','55%', '92.92%',
                  '98.82%','97.90%','50%', '34%','97.15%','92.89%','89.63%','85.37%','84.20%',
                  '91.11%','88.73%', '89.75%','97.15%','92.89%','88.20%']}
  df3 = pd.DataFrame(data=data)
  
  list_quarters =['Q1', 'Q2', 'Q3', 'Q4']
  quarters = pd.DataFrame(list_quarters, columns=['quarters'])
  
  list_years=[2022, 2023, 2024, 2025, 2026, 2027]
  years= pd.DataFrame(list_years, columns=['years'])
  
  year_count = []
  for year in years['years'].unique():
      year_count.append({'label':str(year),'value':year})
  
  dcc.Dropdown(id='drop_year', options=year_count, value=years['years'].min(), 
                   style=dict(width='40%', verticalAlign=&quot;left&quot;, display='inline-block'))
  
  annotations = [dict(
              x=xi,
              y=yi,
              text=str(zi),
              xanchor='auto',
              yanchor='bottom',
              showarrow=False,
              align='center', 
              font=dict(size=8),
          ) for xi, yi, zi in zip(quarters['quarters'], df2['prod'], df3['hcr'])]
  
  app = dash.Dash()
  
  app.layout=html.Div(
      
      children=[
      html.H2(
          children=&quot;&quot;,
          style={
              &quot;font-size&quot;: 14,
              &quot;margin-bottom&quot;: &quot;0em&quot;,
              &quot;margin-top&quot;: &quot;1em&quot;,
              },
          ),
      
      #Dropdown
      dcc.Dropdown(id='drop_year', options=year_count, value=years['years'].min(), 
                   style=dict(width='40%', verticalAlign=&quot;left&quot;, display='inline-block')),
      #Hedge per quarter
      dcc.Graph(id='hedge_type',
                figure = {'data':[
   
                   go.Bar(
                        name='HCR', 
                        x=quarters['quarters'], 
                        y=df3['hcr'],
                        opacity=0,
                        ), 
                    go.Bar(
                        name='PPA',
                        x=quarters['quarters'],
                        y=df1.loc[df1['contract']=='ppa', 'hedge'],
                        opacity=1,
                        ),
                    go.Bar(
                        name='OA',
                        x=quarters['quarters'],
                        y=df1.loc[df1['contract']=='oa', 'hedge'],
                        opacity=0.4,
                        ),
                    go.Bar(
                        name='CR',
                        x=quarters['quarters'],
                        y=df1.loc[df1['contract']=='cr', 'hedge'],
                        opacity=0.25,
                        ),
   
                    go.Bar(
                        name='Production', 
                        x=quarters['quarters'],
                        y=df2['prod'],
                        opacity=0.1
                       ),
                    ],
                    'layout':go.Layout(title='',
                                       annotations=annotations,
                                       xaxis=dict(title='quarter'), 
                                       yaxis=dict(title ='GWh', side='left'),
                                       barmode='overlay',
                                       showlegend=True,
                                       ),
                    }, 
                style={'width': '100%', 'display': 'inline-block', 'vertical-align': 'top'},
                ),
          
          ],
      )
  
  if __name__ == '__main__':
      app.run_server()
  
  @app.callback(Output('hedge_type', 'figure'),
                [Input('drop_year', 'value')])
  
  def update_figure(selected_year):
      filtered_df1 = df1[df1['years'] == selected_year]
      filtered_df2 = df2[df2['years'] == selected_year]
      traces_ppa = []
      traces_oa = []
      traces_cr = []
      for quarter in filtered_df1['quarters'].unique():
          df_h = filtered_df1[filtered_df1['quarters'] == quarter]
          traces_ppa.append(go.Bar(
              name='PPA',
              x=quarters['quarters'],
              y=df_h.loc[df_h['contract']=='PPA', 'hedge']),
              opacity=1,
              ),
          traces_oa.append(go.Bar(
              name='OA',
              x=quarters['quarters'],
              y=df_h.loc[df_h['contract']=='OA', 'hedge']),
              opacity=0.4
              ),
          traces_cr.append(go.Bar(
              name='CR',
              x=quarters['quarters'],
              y=df_h.loc[df_h['contract']=='CR', 'hedge']),
              opacity=0.25,
              ),
  
      for quarter in filtered_df2['quarters'].unique():
          df_p = filtered_df2[filtered_df2['quarters'] == quarter]
          traces_p = []
          traces_p.append(go.Bar(
              name='Production',
              x=quarters['quarters'],
              y=df_p['prod'],
              marker=dict(color=colors['l_green']),
              opacity=0.1,
              
              ))
              
      return {
          'data': (traces_ppa, traces_oa, traces_cr, traces_p),
          'layout': go.Layout(title='',
              annotations=annotations,
              xaxis=dict(gridcolor='#dfe6e9', title='quarter', dtick=1),
              yaxis=dict(gridcolor='#dfe6e9', title= 'GWh', side='left'),
              showlegend = True,
              barmode = &quot;overlay&quot;,
              legend=dict(orientation=&quot;h&quot;, yanchor=&quot;bottom&quot;, y=1.02, xanchor=&quot;right&quot;, x=1),
              hovermode=&quot;x unified&quot;,
          )
      }
  </code></pre>