import dash import dash_core_components as dcc import dash_html_components as html import pandas as pd import plotly.graph_objs as go from dash.dependencies import Output, Input, State import dash_table_experiments as dt from plotly.graph_objs.layout import Margin app = dash.Dash(static_folder='static') app.css.append_css({'external_url': 'https://codepen.io/chriddyp/pen/bWLwgP.css'}) app.css.append_css({'external_url': '/static/styles.css'}) server = app.server try: df = pd.read_pickle('/var/tmp/flights.pkl') except: df = pd.read_csv( 'http://square.github.io/crossfilter/flights-3m.json', parse_dates=['date'], date_parser=lambda s: pd.datetime.strptime(s, '%m%d%H%M')) df.to_pickle('/var/tmp/flights.pkl') df['time'] = df.date.dt.time df = df.sample(frac=0.01) def hist(df, filtered_df, col, selected_points, quantile=None, size=None): filtered_serie = get_serie(col, filtered_df, quantile) if quantile else filtered_df[col] serie = get_serie(col, df, quantile) if quantile else df[col] min_x, max_x = serie.min(), serie.max() if not size: size = (max_x - min_x) / 25 xbins = dict(start=min_x, end=max_x, size=size) if selected_points: selected_points = selected_points[int(len(selected_points) / 2)] data = [ go.Histogram( x=serie, # autobinx=True, xbins=xbins, marker=dict( color='#FFD7E9', ), selectedpoints=selected_points ), go.Histogram( x=filtered_serie, xbins=xbins ), ] layout = go.Layout( margin=Margin( l=5, r=5, b=50, t=50, pad=4 ), bargap=0.1, barmode='overlay', dragmode='select', selectdirection='h', title=col, showlegend=False ) return dcc.Graph( id=col + '-graph', figure={ 'data': data, 'layout': layout } ) def get_serie(col, filtered_df, quantile): mask = filtered_df[col].between( filtered_df[col].quantile(quantile), filtered_df[col].quantile(1 - quantile)) return filtered_df[mask][col] def get_plots(df, filtered_df, delay_select=None, distance_select=None, date_selection=None): return html.Div(id='stuff', children=[ html.Div(id='plots', className='plots', children=[ hist(df, filtered_df, 'delay', delay_select, 0.05), hist(df, filtered_df, 'distance', distance_select, 0.05), # todo: this should be a normal bar chart, not histogram hist(df, filtered_df, 'date', date_selection), # hist(df, filtered_df, 'time', distance_select, size=5000), ]), html.Div('%s / %s' % (filtered_df.shape[0], df.shape[0])), html.Div(id='delay-selection', children=delay_select), html.Div(id='distance-selection', children=distance_select), html.Div(id='date-selection', children=date_selection), dt.DataTable( rows=filtered_df.to_dict('records'), row_selectable=True, filterable=True, sortable=True, selected_row_indices=[], id='datatable' ) ]) app.layout = html.Div(children=[ html.H1(children='Plotly Crossfilter'), html.Div(children=[ "Plotly Dash reproduction of ", html.A( "http://square.github.io/crossfilter", href="http://square.github.io/crossfilter/") ]), html.Div(id='data-viz', children=get_plots(df, df)) ]) @app.callback( Output('data-viz', 'children'), [ Input('delay-graph', 'selectedData'), Input('distance-graph', 'selectedData'), Input('date-graph', 'selectedData'), ], [ State('delay-selection', 'children'), State('distance-selection', 'children'), State('date-selection', 'children'), ] ) def plots(delay_select, distance_select, date_select, delay_selection, distance_selection, date_selection): if delay_select or distance_select or date_select: filtered_df = df.copy() delay_selection = delay_select['range']['x'] if delay_select else delay_selection distance_selection = distance_select['range']['x'] if distance_select else distance_selection date_selection = date_select['range']['x'] if date_select else date_selection if delay_selection: filtered_df = filtered_df[filtered_df['delay'].between(*delay_selection)] if distance_selection: filtered_df = filtered_df[filtered_df['distance'].between(*distance_selection)] if date_selection: filtered_df = filtered_df[filtered_df['date'].between(*date_selection)] else: filtered_df = df delay_selection = distance_selection = None return get_plots(df, filtered_df, delay_selection, distance_selection, date_selection) if __name__ == '__main__': app.run_server(debug=True, port=1234)