title: Uploading a CSV to Plotly Dash and rendering a bar plot based on a Pandas dataframe
body: <p>I'm new to the <code>Plotly Dash</code> framework and have attempted to build a simple dashboard that:</p>
  
  <ol>
  <li><p>Allows the user to upload a CSV file to analyze graphically.</p></li>
  <li><p>Creates a Pandas data frame based on the file uploaded in step #1.</p>
  
  <p>2a. Renders nothing if the CSV file (and resulting data frame) has not been selected.</p></li>
  <li><p>Renders a basic bar plot (or scatter plot, heat map, etc.) based on the data contained in the aforementioned data frame.</p></li>
  </ol>
  
  <p>The data in my CSV file looks similar to the following:</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>My 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>I'm able to upload and view the contents of the CSV file.  </p>
  
  <p><strong>However, the <code>go.Bar()</code> function has its <code>x</code> and <code>y</code> values 'hard-coded' in.  They're not necessarily DYNAMIC (i.e. if the number of x variables changes, etc.).</strong></p>
  
  <p>How do I get Dash to build the bar plot based on the data in the CSV file that's uploaded using the <code>parse_contents(contents, filename, date)</code> function?</p>
  
  <p>I tried to follow along in <a href="https://stackoverflow.com/questions/60223161/using-dash-upload-component-to-upload-csv-file-and-generate-a-graph">Using dash upload component to upload csv file and generate a graph</a>, but was unable to implement that example successfully.</p>
  
  <p>Thanks in advance for helping a newbie get this toy example working!</p>