Issue with plotting uploaded CSV

I’m trying to build a dashboard using plotly/Dash that allows the user to upload a CSV file and then plot the results. I have borrowed from the examples in the dash documentation and tried to piece together an example that plots the graph but I get an error message which I’ve attached below.

My code is attached:

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 dash_table

import pandas as pd

graph_name = 'Time series plot'
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

colors = {
    "graphBackground": "#212529",
    "background": "#000000",
    "text": "#ffffff"
}
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)


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'),
    dcc.Graph(id='new-hydrograph')
])

def parse_contents(contents, filename):
    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.'
        ])
    if df.shape[1] == 4:

        df = df.iloc[2:]
        df.columns = ['Datetime', 'Depth (in)', 'Velocity (feet/sec)', 'Flow (MGD)']
    else:
        df.columns = ['Datetime', 'Rain (in)']

    return df


@app.callback(Output('output-data-upload', 'children'),
              [Input('upload-data', 'contents')],
              [State('upload-data', 'filename')])
def update_output(list_of_contents, list_of_names):
    if list_of_contents is not None:
        children = [
            parse_contents(c, n) for c, n in
            zip(list_of_contents, list_of_names)]
        return children

@app.callback(Output('new-hydrograph', 'figure'),
            [Input('upload-data', 'contents'),
            Input('upload-data', 'filename')])

def plot_graph(contents, filename):

    df = parse_contents(contents, filename)


    trace1 = go.Scatter(
        x = df.date, 
        y = df['Depth (in)'],
        mode = 'lines',
        )
    return {
        'data': [trace1],
        'layout': go.Layout(
            title = graph_name,
            plot_bgcolor = colors["graphBackground"],
            paper_bgcolor = colors["graphBackground"])
    }



if __name__ == '__main__':
    app.run_server(debug=True)

The error message I get is:

Traceback (most recent call last):
  File "C:\Users\hvkumar\AppData\Local\Continuum\Anacond
sk\app.py", line 1997, in __call__
    return self.wsgi_app(environ, start_response)
  File "C:\Users\hvkumar\AppData\Local\Continuum\Anacond
sk\app.py", line 1985, in wsgi_app
    response = self.handle_exception(e)
  File "C:\Users\hvkumar\AppData\Local\Continuum\Anacond
sk\app.py", line 1540, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "C:\Users\hvkumar\AppData\Local\Continuum\Anacond
sk\_compat.py", line 33, in reraise
    raise value
  File "C:\Users\hvkumar\AppData\Local\Continuum\Anacond
sk\app.py", line 1982, in wsgi_app
    response = self.full_dispatch_request()
  File "C:\Users\hvkumar\AppData\Local\Continuum\Anacond
sk\app.py", line 1614, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "C:\Users\hvkumar\AppData\Local\Continuum\Anacond
sk\app.py", line 1517, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "C:\Users\hvkumar\AppData\Local\Continuum\Anacond
sk\_compat.py", line 33, in reraise
    raise value
  File "C:\Users\hvkumar\AppData\Local\Continuum\Anacond
sk\app.py", line 1612, in full_dispatch_request
    rv = self.dispatch_request()
  File "C:\Users\hvkumar\AppData\Local\Continuum\Anacond
sk\app.py", line 1598, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view
  File "C:\Users\hvkumar\AppData\Local\Continuum\Anacond
h-0.39.0-py3.6.egg\dash\dash.py", line 1073, in dispatch
    response.set_data(self.callback_map[output]['callbac
  File "C:\Users\hvkumar\AppData\Local\Continuum\Anacond
h-0.39.0-py3.6.egg\dash\dash.py", line 969, in add_conte
    output_value = func(*args, **kwargs)
  File "C:\Users\hvkumar\Documents\Atlanta\pressure_data
- Copy\app_1.py", line 93, in plot_graph
    df = parse_contents(contents, filename)
  File "C:\Users\hvkumar\Documents\Atlanta\pressure_data
- Copy\app_1.py", line 50, in parse_contents
    content_type, content_string = contents.split(',')
AttributeError: 'list' object has no attribute 'split'

Here’s an example CSV

PRC-01   "Average=15min"     "QualityFlag=FALSE"     "QualityValue=FALSE"
DateTime     "MP1\DFINAL"    "MP1\VFINAL"    "MP1\QFINAL"
M/d/yyyy h:mm:ss tt  "inches"    "feet/sec"  "MGD"
1/1/2015 0:00   14.9748 3.69    7.976
1/1/2015 0:15   15.0504 3.64    7.934
1/1/2015 0:30   14.7672 3.79    8.047
1/1/2015 0:45   14.9844 3.68    7.97
1/1/2015 1:00   14.8416 3.52    7.53
1/1/2015 1:15   14.7108 3.55    7.497

Python lists cannot be divided into separate lists based on characters that appear in the values of a list. This is unlike strings which values can be separated into a list. The AttributeError is an exception thrown when an object does not have the attribute you tried to access. The ‘list’ object has no attribute ‘split’ and you’re trying to call python split function on the whole list of lines, and you can’t split a list of strings, only a string. So, you need to split each line, not the whole thing.

To solve the above problem, you need to iterate over the strings in the list to get individual strings; then, you can call the split() function.