User Interface


In [1]:
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
import pandas as pd
import plotly
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
from plotly_usmap import usmap

1. Set up options for Dropdowns and Slider


In [2]:
rank = pd.read_csv('../data/rank_file.csv')

# Create a list of indicators 
available = list(rank.columns.values)
for i in ['Unnamed: 0','City','State','Population','Natural_total_rank', 'Human_related_rank', 
          'Economy_rank', 'Tertiary_Rank', 'Latitude', 'Longitude']:
    available.remove(i)
    
# Create a list of labels for dropdown
labels = ['Fewer Crimes','More Hospitals','Early Education Options',
          'University Options','Air Quality','Water Quality',
           'Fewer Toxics','Fewer Hazardous Particles','Green Coverage',
           'Employment Rate','Sales Revenue','Income','Tuition Affordability',
          'Bars','Restaurants','Museums','Libraries','Parks','Top Restaurants']

# Put available and labels in a two-dimensional list
pairs = [available,labels]

In [3]:
import data_processing as dp
(natural, human, economy, tertiary) = dp.read_data()
alldata = human
for i in[natural, economy, tertiary]:
    factors = list(i.columns.values)
    for j in factors:
        alldata[j] = i[j]
imp = pd.DataFrame()
imp['City'] = alldata['City']
imp['Population'] = alldata['Population'] 
imp['Crime'] = alldata['Violent'] + alldata['Rape'] + alldata['Robbery']
imp['Colleges'] = alldata['Colleges']
imp['Hospitals'] = alldata['NumHospital']
imp['Air Score'] = alldata['Air']
imp['Water Score'] = alldata['Water_quality']
imp['Median Income'] = alldata['Median Income']
imp['Restaurants'] = alldata['Restaurant']
imp['Pro Sport team'] = alldata['Pro_sports_team']
f = list(imp.columns.values)
f.remove('City')
f.remove('Population')

2. Set up layout for User Interface


In [4]:
app = dash.Dash()
# Get DataFrame value
import UI_setup
app.layout = UI_setup.layout_setup(pairs, f)

3.Set up for default graph


In [5]:
@app.callback(
    dash.dependencies.Output('graph-with-slider', 'figure'),
    [dash.dependencies.Input('factor', 'value')])
def update_figure(factor):
    choose = f[factor]
    return {
        'data': [go.Scatter(
            x=imp['Population'],
            y=imp[choose],
            text=imp['City'],
            mode='markers',
            opacity=0.7,
            marker={
                'size': 15,
                'line': {'width': 0.5, 'color': 'white'}
            }
        )],
        'layout': go.Layout(
            xaxis={
                'title': 'Population',
                'type': 'linear' 
            },
            yaxis={
                'title': choose,
                'type': 'linear' 
            },
            margin={'l': 40, 'b': 30, 't': 10, 'r': 0},
            hovermode='closest'
        )
    }

In [6]:
@app.callback(
    dash.dependencies.Output('Total-graphic', 'figure'),
    [dash.dependencies.Input('Total', 'n_clicks')]
)
def total_graph(Total):
    if(Total is None):
        return
    #Total general rank
    return {
           usmap(rank)    
        }

In [7]:
@app.callback(
    dash.dependencies.Output('Human-graphic', 'figure'),
    [dash.dependencies.Input('Hrank', 'n_clicks')]
)
def human_graph(Hrank):
    if(Hrank is None):
        return
    #Total general rank
    return {
           usmap(rank, 'human')    
        }

In [8]:
@app.callback(
    dash.dependencies.Output('Natural-graphic', 'figure'),
    [dash.dependencies.Input('Nrank', 'n_clicks')]
)
def natural_graph(Nrank):
    if(Nrank is None):
        return
    #Total general rank
    return {
           usmap(rank, 'natural')    
        }

In [9]:
@app.callback(
    dash.dependencies.Output('Economic-graphic', 'figure'),
    [dash.dependencies.Input('Erank', 'n_clicks')]
)
def economomic_graph(Erank):
    if(Erank is None):
        return
    #Total general rank
    return {
           usmap(rank, 'economy')    
        }

In [10]:
@app.callback(
    dash.dependencies.Output('Tertiary-graphic', 'figure'),
    [dash.dependencies.Input('Trank', 'n_clicks')]
)
def teritary_graph(Trank):
    if(Trank is None):
        return
    #Total general rank
    return {
           usmap(rank, 'tertiary')    
        }

4.Set up for user call


In [11]:
@app.callback(
    dash.dependencies.Output('User-graphic', 'figure'),
    [dash.dependencies.Input('Search', 'n_clicks')],
    [dash.dependencies.State('First-care', 'value'),
     dash.dependencies.State('Second-care', 'value'),
     dash.dependencies.State('Third-care', 'value'),
     dash.dependencies.State('Fourth-care', 'value'),
     dash.dependencies.State('Fifth-care', 'value'),
    ]
)
    
def user_DIY_graph(Search, First_care, Second_care, Third_care, Fourth_care, Fifth_care):
    df = UI_setup.newdf(rank, First_care, Second_care, Third_care, Fourth_care, Fifth_care)
    
    limits = [(0,10),(10,20),(20,30),(30,40),(40,50)]
    colors = ["rgb(0,116,217)","rgb(255,65,54)","rgb(133,20,75)","rgb(255,133,27)","lightgrey"]
    cities = []


    for i in range(len(limits)):
        lim = limits[i]
        df_sub = df[lim[0]:lim[1]]
        city = dict(
            type = 'scattergeo',
            locationmode = 'USA-states',
            lon = df_sub['longitude'],
            lat = df_sub['latitude'],
            text = df_sub['text'],
            marker = dict(
                size = df_sub['reverse_rank']*15,
                color = colors[i],
                line = dict(width=0.5, color='rgb(40,40,40)'),
                sizemode = 'area'
            ),
            name = '{0} - {1}'.format(lim[0],lim[1]) )
        cities.append(city)

        layout = dict(
            title = 'Your Dream City Results',
            showlegend = True,
            geo = dict(
                scope='usa',
                projection=dict( type='albers usa' ),
                showland = True,
                landcolor = 'rgb(217, 217, 217)',
                subunitwidth=1,
                countrywidth=1,
                subunitcolor="rgb(255, 255, 255)",
                countrycolor="rgb(255, 255, 255)"
            ),
        )
        fig = dict( data=cities, layout=layout )
        
    return {   
        plotly.offline.plot( fig, validate=False )     
    }

5. Running


In [12]:
app.run_server()


 * Running on http://127.0.0.1:8050/ (Press CTRL+C to quit)
127.0.0.1 - - [05/Dec/2017 22:27:22] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [05/Dec/2017 22:27:23] "GET /_dash-layout HTTP/1.1" 200 -
127.0.0.1 - - [05/Dec/2017 22:27:23] "GET /_dash-dependencies HTTP/1.1" 200 -
[2017-12-05 22:27:23,095] ERROR in app: Exception on /_dash-update-component [POST]
Traceback (most recent call last):
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\flask\app.py", line 1982, in wsgi_app
    response = self.full_dispatch_request()
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\flask\app.py", line 1614, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\flask\app.py", line 1517, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\flask\_compat.py", line 33, in reraise
    raise value
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\flask\app.py", line 1612, in full_dispatch_request
    rv = self.dispatch_request()
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\flask\app.py", line 1598, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\dash\dash.py", line 541, in dispatch
    return self.callback_map[target_id]['callback'](*args)
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\dash\dash.py", line 498, in add_context
    output_value = func(*args, **kwargs)
  File "<ipython-input-11-369b75c3ca70>", line 13, in user_DIY_graph
    df = UI_setup.newdf(rank, First_care, Second_care, Third_care, Fourth_care, Fifth_care)
  File "C:\Users\zhang\Documents\cse583\project\uwseds-group-city-fynders\cityfynders\UI_setup.py", line 148, in newdf
    df['First'] = rank[First_care]
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\pandas\core\frame.py", line 1964, in __getitem__
    return self._getitem_column(key)
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\pandas\core\frame.py", line 1971, in _getitem_column
    return self._get_item_cache(key)
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\pandas\core\generic.py", line 1645, in _get_item_cache
    values = self._data.get(item)
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\pandas\core\internals.py", line 3599, in get
    raise ValueError("cannot label index with a null key")
ValueError: cannot label index with a null key
127.0.0.1 - - [05/Dec/2017 22:27:23] "POST /_dash-update-component HTTP/1.1" 500 -
127.0.0.1 - - [05/Dec/2017 22:27:23] "POST /_dash-update-component HTTP/1.1" 200 -
127.0.0.1 - - [05/Dec/2017 22:27:23] "POST /_dash-update-component HTTP/1.1" 200 -
127.0.0.1 - - [05/Dec/2017 22:27:23] "POST /_dash-update-component HTTP/1.1" 200 -
127.0.0.1 - - [05/Dec/2017 22:27:23] "POST /_dash-update-component HTTP/1.1" 200 -
127.0.0.1 - - [05/Dec/2017 22:27:23] "POST /_dash-update-component HTTP/1.1" 200 -
127.0.0.1 - - [05/Dec/2017 22:27:23] "POST /_dash-update-component HTTP/1.1" 200 -
127.0.0.1 - - [05/Dec/2017 22:27:23] "GET /favicon.ico HTTP/1.1" 200 -
[2017-12-05 22:27:25,437] ERROR in app: Exception on /_dash-update-component [POST]
Traceback (most recent call last):
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\flask\app.py", line 1982, in wsgi_app
    response = self.full_dispatch_request()
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\flask\app.py", line 1614, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\flask\app.py", line 1517, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\flask\_compat.py", line 33, in reraise
    raise value
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\flask\app.py", line 1612, in full_dispatch_request
    rv = self.dispatch_request()
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\flask\app.py", line 1598, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\dash\dash.py", line 541, in dispatch
    return self.callback_map[target_id]['callback'](*args)
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\dash\dash.py", line 509, in add_context
    cls=plotly.utils.PlotlyJSONEncoder),
  File "C:\Users\zhang\Documents\anaconda\lib\json\__init__.py", line 238, in dumps
    **kw).encode(obj)
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\plotly\utils.py", line 136, in encode
    encoded_o = super(PlotlyJSONEncoder, self).encode(o)
  File "C:\Users\zhang\Documents\anaconda\lib\json\encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "C:\Users\zhang\Documents\anaconda\lib\json\encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\plotly\utils.py", line 204, in default
    return _json.JSONEncoder.default(self, obj)
  File "C:\Users\zhang\Documents\anaconda\lib\json\encoder.py", line 180, in default
    o.__class__.__name__)
TypeError: Object of type 'set' is not JSON serializable
127.0.0.1 - - [05/Dec/2017 22:27:25] "POST /_dash-update-component HTTP/1.1" 500 -
[2017-12-05 22:27:37,989] ERROR in app: Exception on /_dash-update-component [POST]
Traceback (most recent call last):
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\flask\app.py", line 1982, in wsgi_app
    response = self.full_dispatch_request()
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\flask\app.py", line 1614, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\flask\app.py", line 1517, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\flask\_compat.py", line 33, in reraise
    raise value
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\flask\app.py", line 1612, in full_dispatch_request
    rv = self.dispatch_request()
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\flask\app.py", line 1598, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\dash\dash.py", line 541, in dispatch
    return self.callback_map[target_id]['callback'](*args)
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\dash\dash.py", line 509, in add_context
    cls=plotly.utils.PlotlyJSONEncoder),
  File "C:\Users\zhang\Documents\anaconda\lib\json\__init__.py", line 238, in dumps
    **kw).encode(obj)
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\plotly\utils.py", line 136, in encode
    encoded_o = super(PlotlyJSONEncoder, self).encode(o)
  File "C:\Users\zhang\Documents\anaconda\lib\json\encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "C:\Users\zhang\Documents\anaconda\lib\json\encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "C:\Users\zhang\Documents\anaconda\lib\site-packages\plotly\utils.py", line 204, in default
    return _json.JSONEncoder.default(self, obj)
  File "C:\Users\zhang\Documents\anaconda\lib\json\encoder.py", line 180, in default
    o.__class__.__name__)
TypeError: Object of type 'set' is not JSON serializable
127.0.0.1 - - [05/Dec/2017 22:27:37] "POST /_dash-update-component HTTP/1.1" 500 -