title: How to feed the x and y values of a Plotly bar chart from a Pandas data frame
body: <p>I have the following toy data set:</p>
  
  <pre><code>df = pd.DataFrame({'Make':['Ford', 'Ford', 'Ford', 'BMW', 'BMW', 'BMW', Mercedes', 'Mercedes', 'Mercedes'],
                            'Score':['88.6', '76.6', '100', '79.1', '86.8', '96.4', '97.3', '98.7', '98.5'],
                            'Dimension':['Speed', 'MPG', 'Styling', 'Speed', 'MPG', 'Styling', 'Speed', 'MPG', 'Styling'],
                            'Month':['Apr-19', 'Apr-19', 'Apr-19', 'Apr-19', 'Apr-19', 'Apr-19', 'Apr-19', 'Apr-19', 'Apr-19']})
  </code></pre>
  
  <p>I'm using <code>Plotly</code> and the <code>Dash</code> framework to build an interactive web-based dashboard.  The code is as follows:</p>
  
  <pre><code>import base64
  import datetime
  import io
  import dash
  from dash.dependencies import Input, Output, State
  import dash_core_components as dcc
  import dash_html_components as html
  import plotly.graph_objects as go
  import dash_table
  import pandas as pd
  
  
  app = dash.Dash()
  
  app.layout = html.Div([
  dcc.Upload(
          id='upload-data',
          children=html.Div([
          'Drag and Drop or ',
          html.A('Select Files')
          ]),
          style={
          'width': '100%',
          'height': '60px',
          'lineHeight': '60px',
          'borderWidth': '1px',
          'borderStyle': 'dashed',
          'borderRadius': '5px',
          'textAlign': 'center',
          'margin': '10px'
           },
          # Allow multiple files to be uploaded
          multiple=True
  ),
  
  html.Div(id='output-data-upload'),
  ])
  
  def parse_contents(contents, filename, date):
      content_type, content_string = contents.split(',')
  
      decoded = base64.b64decode(content_string)
      try:
          if 'csv' in filename:
          # Assume that the user uploaded a CSV file
              df = pd.read_csv(
                  io.StringIO(decoded.decode('utf-8')))
          elif 'xls' in filename:
          # Assume that the user uploaded an excel file
              df = pd.read_excel(io.BytesIO(decoded))
      except Exception as e:
          print(e)
          return html.Div([
              'There was an error processing this file.'
          ])
  
      return html.Div([
          html.H5(filename),
          html.H6(datetime.datetime.fromtimestamp(date)),
  
          dash_table.DataTable(
              data=df.to_dict('records'),
              columns=[{'name': i, 'id': i} for i in df.columns]
          ),
  
          html.Hr(),  # horizontal line
  
          #### How to get the x and y values DYNAMICALLY from the data frame to pass into the Bar() function? ####
  
          dcc.Graph(
              figure = go.Figure(data=[
              go.Bar(name=df.columns.values[0], x=pd.unique(df['Make']), y=[88.6, 76.6, 100], text=[88.6, 76.6, 100], textposition='auto'),
              go.Bar(name=df.columns.values[1], x=pd.unique(df['Make']), y=[92.5, 93.6, 93.4], text=[92.5, 93.6, 93.4], textposition='auto'),
              go.Bar(name=df.columns.values[2], x=pd.unique(df['Make']), y=[99.1, 99.2, 95.9], text=[99.1, 99.2, 95.9], textposition='auto'),
              ])
              ),        
  
  
          html.Hr(),
  
          # For debugging, display the raw contents provided by the web browser
          html.Div('Raw Content'),
          html.Pre(contents[0:200] + '...', style={
              'whiteSpace': 'pre-wrap',
              'wordBreak': 'break-all'
          })
      ])
  
  @app.callback(Output('output-data-upload', 'children'),
                [Input('upload-data', 'contents')],
                [State('upload-data', 'filename'),
                 State('upload-data', 'last_modified')])
  def update_output(list_of_contents, list_of_names, list_of_dates):
      if list_of_contents is not None:
          children = [
              parse_contents(c, n, d) for c, n, d in
              zip(list_of_contents, list_of_names, list_of_dates)]
          return children
  
  if __name__ == '__main__':
      app.run_server(debug=True)
  </code></pre>
  
  <p>In summary, the user uploads a .csv file and a <code>Pandas data frame</code> is created.  A bar plot is then rendered based on the data in the data frame.</p>
  
  <p>As you can see, the <code>go.Bar()</code> function has <code>x</code> and <code>y</code> values that come from the <code>df</code> dataframe.  The number of <code>x</code> values can fluctuate (in this case, it's 3, but it could be 2 or 10 or anywhere in between).  I have the <code>x</code> values hard-coded in a very inelegant way as indexed values from the column names.</p>
  
  <p>Questions:</p>
  
  <p>1) What's the most Pythonic way to read in the <code>x</code> values dynamically, such that the code accepts a variable number of <code>x</code> values?</p>
  
  <p>2) What is the best way to read in the associated <code>y</code> values dynamically from the <code>df</code> data frame? (I have them completely hard-coded in for the purposes of this example)</p>
  
  <p>Thanks in advance?</p>