Related
So i am traying to make a cycle that gives different sankey diagram the thing is due to the plotly optimization the node are in different positions. I will like to set the standard order to be [Formal, Informal, Unemployed, Inactive]
import matplotlib.pyplot as plt
import pandas as pd
import plotly.graph_objects as go
df = pd.read_csv(path, delimiter=",")
Lista_Paises = df["code"].unique().tolist()
Lista_DF = []
for x in Lista_Paises:
DF_x = df[df["code"] == x]
Lista_DF.append(DF_x)
def grafico(df):
df = df.astype({"Source": "category", "Value": "float", "Target": "category"})
def category(i):
if i == "Formal":
return 0
if i == "Informal":
return 1
if i == "Unemployed":
return 2
if i == "Inactive":
return 3
def color(i):
if i == "Formal":
return "#9FB5D5"
if i == "Informal":
return "#E3EEF9"
if i == "Unemployed":
return "#E298AE"
if i == "Inactive":
return "#FCEFBC"
df['Source_cat'] = df["Source"].apply(category).astype("int")
df['Target_cat'] = df["Target"].apply(category).astype("int")
# df['Source_cat'] = LabelEncoder().fit_transform(df.Source)
# df['Target_cat'] = LabelEncoder().fit_transform(df.Target)
df["Color"] = df["Source"].apply(color).astype("str")
df = df.sort_values(by=["Source_cat", "Target_cat"])
Lista_Para_Sumar = df["Source_cat"].nunique()
Lista_Para_Tags = df["Source"].unique().tolist()
Suma = Lista_Para_Sumar
df["out"] = df["Target_cat"] + Suma
TAGS = Lista_Para_Tags + Lista_Para_Tags
Origen = df['Source_cat'].tolist()
Destino = df["out"].tolist()
Valor = df["Value"].tolist()
Color = df["Color"].tolist()
return (TAGS, Origen, Destino, Valor, Color)
def Sankey(TAGS: object, Origen: object, Destino: object, Valor: object, Color: object, titulo: str) -> object:
label = TAGS
source = Origen
target = Destino
value = Valor
link = dict(source=source, target=target, value=value,
color=Color)
node = dict(x=[0, 0, 0, 0, 1, 1, 1, 1], y=[1, 0.75, 0.5, 0.25, 0, 1, 0.75, 0.5, 0.25, 0], label=label, pad=35,
thickness=10,
color=["#305CA3", "#C1DAF1", "#C9304E", "#F7DC70", "#305CA3", "#C1DAF1", "#C9304E", "#F7DC70"])
data = go.Sankey(link=link, node=node, arrangement='snap')
fig = go.Figure(data)
fig.update_layout(title_text=titulo + "-" + "Mujeres", font_size=10, )
plt.plot(alpha=0.01)
titulo_guardar = (str(titulo) + ".png")
fig.write_image("/Users/agudelo/Desktop/GRAFICOS PNUD/Graficas/MUJERES/" + titulo_guardar, engine="kaleido")
for y in Lista_DF:
TAGS, Origen, Destino, Valor, Color = grafico(y)
titulo = str(y["code"].unique())
titulo = titulo.replace("[", "")
titulo = titulo.replace("]", "")
titulo = titulo.replace("'", "")
Sankey(TAGS, Origen, Destino, Valor, Color, titulo)
The expected result should be.
The expected result due to the correct order:
The real result i am getting is:
I had a similar problem earlier. I hope this will work for you. As I did not have your data, I created some dummy data. Sorry about the looooong explanation. Here are the steps that should help you reach your goal...
This is what I did:
Order the data and sort it - used pd.Categorical to set the order and then df.sort to sort the data so that the input is sorted by source and then destination.
For the sankey node, you need to set the x and y positions. x=0, y=0 starts at top left. This is important as you are telling plotly the order you want the nodes. One weird thing is that it sometimes errors if x or y is at 0 or 1. Keep it very close, but not the same number... wish I knew why
For the other x and y entries, I used ratios as my total adds up to 285. For eg. Source-Informal starts at x = 0.001 and y = 75/285 as Source-Formal = 75 and this will start right after that
Based on step 1, the link -> source and destination should also be sorted. But, pls do check.
Note: I didn't color the links, but think you already have achieved that...
Hope this helps resolve your issue...
My data - sankey.csv
source,destination,value
Formal,Formal,20
Formal,Informal, 10
Formal,Unemployed,30
Formal,Inactive,15
Informal,Formal,20
Informal,Informal,15
Informal,Unemployed,25
Informal,Inactive,25
Unemployed,Formal,5
Unemployed,Informal,10
Unemployed,Unemployed,10
Unemployed,Inactive,5
Inactive,Formal,30
Inactive,Informal,20
Inactive,Unemployed,20
Inactive,Inactive,25
The code
import plotly.graph_objects as go
import pandas as pd
df = pd.read_csv('sankey.csv') #Read above CSV
#Sort by Source and then Destination
df['source'] = pd.Categorical(df['source'], ['Formal','Informal', 'Unemployed', 'Inactive'])
df['destination'] = pd.Categorical(df['destination'], ['Formal','Informal', 'Unemployed', 'Inactive'])
df.sort_values(['source', 'destination'], inplace = True)
df.reset_index(drop=True)
mynode = dict(
pad = 15,
thickness = 20,
line = dict(color = "black", width = 0.5),
label = ['Formal', 'Informal', 'Unemployed', 'Inactive', 'Formal', 'Informal', 'Unemployed', 'Inactive'],
x = [0.001, 0.001, 0.001, 0.001, 0.999, 0.999, 0.999, 0.999],
y = [0.001, 75/285, 160/285, 190/285, 0.001, 75/285, 130/285, 215/285],
color = ["#305CA3", "#C1DAF1", "#C9304E", "#F7DC70", "#305CA3", "#C1DAF1", "#C9304E", "#F7DC70"])
mylink = dict(
source = [ 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3 ],
target = [ 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7 ],
value = df.value.to_list())
fig = go.Figure(data=[go.Sankey(
arrangement='snap',
node = mynode,
link = mylink
)])
fig.update_layout(title_text="Basic Sankey Diagram", font_size=20)
fig.show()
The output
I'm pretty much a beginner in plotly/pandas/data but I'm trying to make this graph and no matter what I search up, I can't find any attributes that are compatible with dictionaries. The data I'm using is the Time series download speed for 9 different software. I am trying to display the box plot descending by their median values.
Here is my code:
import pandas as pd
import plotly.graph_objs as go
from plotly.offline import plot
import numpy as np
olddf = pd.read_csv("justice.csv")
df = olddf.interpolate()
col = df.loc[:,'Bfy':'Sfy']
df["1"] = col.mean(axis=1)
col2 = df.loc[:,'Bakamai':'Sakamai']
df["2"] = col2.mean(axis=1)
col4 = df.loc[:,'Bazure':'Sazure']
df["4"] = col4.mean(axis=1)
col5 = df.loc[:,'Bcloudflare':'Scloudflare']
df["5"] = col5.mean(axis=1)
col6 = df.loc[:,'Bfastly':'Sfastly']
df["6"] = col6.mean(axis=1)
col7 = df.loc[:,'BAWS':'SAWS']
df["7"] = col7.mean(axis=1)
col8 = df.loc[:,'Bali':'Sali']
df["8"] = col8.mean(axis=1)
col9 = df.loc[:,'Bgoog':'Sgoog']
df["9"] = col9.mean(axis=1)
trace_one = go.Box(
y=df['1'],
name="Fy",
line = dict(color='#8235EA'),
opacity = 0.8)
trace_two = go.Box(
y=df['2'],
name="Akamai",
line = dict(color='#EA8933'),
opacity = 0.8)
trace_four = go.Box(
y=df['4'],
name="Azure",
line = dict(color='#62F92C'),
opacity = 0.8)
trace_five = go.Box(
y=df['5'],
name="Cloudflare",
line = dict(color='#3548EA'),
opacity = 0.8)
trace_six = go.Box(
y=df['6'],
name="Fastly",
line = dict(color='#D735EA'),
opacity = 0.8)
trace_seven = go.Box(
y=df['7'],
name="AWS Cloudfront",
line = dict(color='#29E5B7'),
opacity = 0.8)
trace_eight = go.Box(
y=df['8'],
name="Alibaba Cloud",
line = dict(color='#3597EA'),
opacity = 0.8)
trace_nine = go.Box(
y=df['9'],
name="Google Cloud",
line = dict(color='#EA4833'),
opacity = 0.8,
)
data=[trace_one, trace_four, trace_seven, trace_eight, trace_nine, trace_five, trace_two]
layout = dict(
title = "CHINA - Software vs Mb loaded per second")
fig = dict(data=data, layout=layout)
plot(fig)
csv layout example:
datetime,Bfy,Sfy,Gfy,Bakamai,Sakamai,Gakamai,Bazuaka,Sazuaka,Gazuaka,Bazure,Sazure,Gazure,Bcloudflare,Scloudflare,Gcloudflare,Bfastly,Sfastly,Gfastly,BAWS,SAWS,GAWS,Bali,Sali,Gali,Bgoog,Sgoog,Ggoog
23/07/21 10:02PM,,,215200,1489,1571,,1897,12400,173600,6551,,,1556,769,,,,749,6124,9347,2179,4160,,4473,4635,906,3426
23/07/21 10:12PM,22653,21520,,,1670,,17360,,,,10850,,,18261,1522,,3414,2010,5148,10447,2030,2667,4160,4119,5837,1592,3216
23/07/21 10:22PM,23911,,,1535,1615,815,3156,13354,177,6313,,,,825,586,873,,885,4280,6458,2114,4039,4119,6303,5629,1072,3283
taken a different approach to data preparation
pair columns, calculate means
create new dataframe from these paired column means
order columns of this data preparation based on their medians
create box plots in same order as ordered columns
found two providers that your code did not plot...
import plotly.graph_objects as go
import pandas as pd
import io
df = pd.read_csv(io.StringIO("""datetime,Bfy,Sfy,Gfy,Bakamai,Sakamai,Gakamai,Bazuaka,Sazuaka,Gazuaka,Bazure,Sazure,Gazure,Bcloudflare,Scloudflare,Gcloudflare,Bfastly,Sfastly,Gfastly,BAWS,SAWS,GAWS,Bali,Sali,Gali,Bgoog,Sgoog,Ggoog
23/07/21 10:02PM,,,215200,1489,1571,,1897,12400,173600,6551,,,1556,769,,,,749,6124,9347,2179,4160,,4473,4635,906,3426
23/07/21 10:12PM,22653,21520,,,1670,,17360,,,,10850,,,18261,1522,,3414,2010,5148,10447,2030,2667,4160,4119,5837,1592,3216
23/07/21 10:22PM,23911,,,1535,1615,815,3156,13354,177,6313,,,,825,586,873,,885,4280,6458,2114,4039,4119,6303,5629,1072,3283"""))
# different approach to getting means per provider to plot
df2 = pd.DataFrame({c[1:]:df.loc[:,[c, "S"+c[1:]]].mean(axis=1).values for c in df.columns if c[0]=="B"})
# re-order columns on ascending median
df2 = df2.reindex(df2.median().sort_values().index, axis=1)
meta = {'fy': {'color': '#8235EA', 'name': 'Fy'},
'azure': {'color': '#62F92C', 'name': 'Azure'},
'AWS': {'color': '#29E5B7', 'name': 'AWS Cloudfront'},
'ali': {'color': '#3597EA', 'name': 'Alibaba Cloud'},
'goog': {'color': '#EA4833', 'name': 'Google Cloud'},
'cloudflare': {'color': '#3548EA', 'name': 'Cloudflare'},
'akamai': {'color': '#EA8933', 'name': 'Akamai'},
# next two were missing
'fastly': {'color': 'pink', 'name': 'Fastly'},
'azuaka': {'color': 'purple', 'name': 'azuaka'},
}
go.Figure([go.Box(y=df2[c], name=meta[c]["name"], line={"color":meta[c]["color"]}) for c in df2.columns])
I'm trying to generate a Dash app which displays historical and forecasted housing prices. I've got the forecasted data stored in a different dataframe from the historical prices, and I'd like to plot them both on the same graph in Dash, and have the graph get updated via callback when the user picks a different city from a dropdown menu. I would like both traces of the graph to update when a value is selected in the dropdown. I've tried various things but can only get one trace from one dataframe plotted for the graph in my callback:
# --- import libraries ---
import dash
import dash_table
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import numpy as np
import plotly.express as px
import plotly.graph_objects as go
from dash.dependencies import Output, Input
# --- load data ---
df_h = pd.read_csv('df_h.csv')
df_arima = pd.read_csv('df_arima.csv')
options = [] #each column in the df_h dataframe is an option for the dropdown menu
for column in df_h.columns:
options.append({'label': '{}'.format(column, column), 'value': column})
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
# --- initialize the app ---
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
# --- layout the dashboard ---
app.layout = html.Div(
children = [
html.Div([
html.Label('Select a feature from drop-down to plot'),
dcc.Dropdown(
id = 'city-dropdown',
options = options,
value = 'Denver, CO',
multi = False,
clearable = True,
searchable = True,
placeholder = 'Choose a City...'),
html.Div(id = 'forecast-container',
style = {'padding': '50px'}),
]),
],
)
# --- dropdown callback ---
#app.callback(
Output('forecast-container', 'children'),
Input('city-dropdown', 'value'))
def forecast_graph(value):
dff = df_h[['Date', value]] #'value' is identical between the two dataframes. references
dfa = df_arima[df_arima['City'] == value] # a col in dff and row values in dfa
return [
dcc.Graph(
id = 'forecast-graph',
figure = px.line(
data_frame = dff,
x = 'Date',
y = value).update_layout(
showlegend = False,
template = 'xgridoff',
yaxis = {'title': 'Median Home Price ($USD)'},
xaxis = {'title': 'Year'},
title = {'text': 'Median Home Price vs. Year for {}'.format(value),
'font': {'size': 24}, 'x': 0.5, 'xanchor': 'center'}
),
)
]
I was able to accomplish this in Plotly but can't figure out how to do it in Dash. This is what I want in Dash:
Plotly graph I am trying to reproduce in callback, that is linked to a dropdown menu
This is all I can get to work in Dash:
Only one dataframe plots in Dash
This is the code that works in plotly graph objects:
from statsmodels.tsa.arima_model import ARIMA
df_ml = pd.read_csv('df_ml.csv')
# --- data cleaning ---
df_pred = df_ml[df_ml['RegionName'] == city]
df_pred = df_pred.transpose().reset_index().drop([0])
df_pred.columns = ['Date', 'MedianHomePrice_USD']
df_pred['MedianHomePrice_USD'] = df_pred['MedianHomePrice_USD'].astype('int')
df_pred['Date'] = pd.to_datetime(df_pred['Date'])
df_pred['Date'] = df_pred['Date'].dt.strftime('%Y-%m')
df_model = df_pred.set_index('Date')
model_data = df_model['MedianHomePrice_USD']
def house_price_forecast(model_data, forecast_steps, city):
#--- ARIMA Model (autoregressive integrated moving average) ---
model = ARIMA(model_data, order = (2,1,2), freq = 'MS')
res = model.fit()
forecast = res.forecast(forecast_steps)
forecast_mean = forecast[0]
forecast_se = forecast[1]
forecast_ci = forecast[2]
df_forecast = pd.DataFrame()
df_forecast['Mean'] = forecast_mean.T
df_forecast['Lower_ci'], df_forecast['Upper_ci'] = forecast_ci.T
df_forecast['Date'] = pd.date_range(start = '2021-02', periods = forecast_steps, freq = 'MS')
df_forecast['Date'] = df_forecast['Date'].dt.strftime('%Y-%m')
df_forecast.index = df_forecast['Date']
fig = go.Figure()
fig.add_trace(go.Scatter(x = df_pred['Date'], y = df_pred['MedianHomePrice_USD'],
mode = 'lines', name = 'Median Home Price ($USD)',
line_color = 'rgba(49, 131, 189, 0.75)', line_width = 2))
fig.add_trace(go.Scatter(x = df_forecast.index, y = df_forecast['Mean'],
mode = 'lines', line_color = '#e6550d',
name = 'Forecast mean'))
fig.add_trace(go.Scatter(x = df_forecast.index, y = df_forecast['Upper_ci'],
mode = 'lines', line_color = '#e0e0e0', fill = 'tonexty',
fillcolor = 'rgba(225,225,225, 0.3)',
name = 'Upper 95% confidence interval'))
fig.add_trace(go.Scatter(x = df_forecast.index, y = df_forecast['Lower_ci'],
mode = 'lines', line_color = '#e0e0e0', fill = 'tonexty',
fillcolor = 'rgba(225,225,225, 0.3)',
name = 'Lower 95% confidence interval'))
fig.update_layout(title = 'Median Home Price in {}, {} - {} (Predicted)'.format(
city, model_data.idxmin()[:-3], df_forecast_mean.idxmax()[:-3]),
xaxis_title = 'Year', yaxis_title = 'Median Home Price ($USD)',
template = 'xgridoff')
fig.show()
house_price_forecast(model_data, 24, 'Denver, CO') #24 month prediction
Perhaps a more succinct way of asking this question: How do I add a trace to an existing Dash graph, with data from a different dataframe, and both traces get updated when the user selects a value from a single dropdown?
Figured it out...
Don't use the syntax I used above in your callback. Put the px.line call inside a variable(fig, in this case), and then use fig.add_scatter to add data from a different dataframe to the graph. Both parts of the graph will update from the callback.
Also, fig.add_scatter doesn't have a dataframe argument, so use df.column or df[column] (ex. 'dfa.Date' below)
# --- import libraries ---
import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import plotly.express as px
from dash.dependencies import Output, Input
# --- load data ---
df_h = pd.read_csv('df_h.csv')
df_h['Date'] = pd.to_datetime(df_h['Date'])
df_arima = pd.read_csv('df_arima.csv')
df_arima['Date'] = pd.to_datetime(df_arima['Date'])
df_arima['Date'] = df_arima['Date'].dt.strftime('%Y-%m')
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
# --- initialize the app ---
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([
dcc.Graph(id = 'forecast-container')
]
)
# --- dropdown callback ---
#app.callback(
Output('forecast-container', 'figure'),
Input('city-dropdown', 'value'))
def update_figure(selected_city):
dff = df_h[['Date', selected_city]]
# dff[selected_city] = dff[selected_city].round(0)
dfa = df_arima[df_arima['City'] == selected_city]
fig = px.line(dff, x = 'Date', y = selected_city,
hover_data = {selected_city: ':$,f'})
fig.add_scatter(x = dfa.Date, y = dfa.Mean,
line_color = 'orange', name = 'Forecast Mean')
fig.add_scatter(x = dfa.Date, y = dfa.Lower_ci,
fill = 'tonexty', fillcolor = 'rgba(225,225,225, 0.3)',
marker = {'color': 'rgba(225,225,225, 0.9)'},
name = 'Lower 95% Confidence Interval')
fig.add_scatter(x = dfa.Date, y = dfa.Upper_ci,
fill = 'tonexty', fillcolor = 'rgba(225,225,225, 0.3)',
marker = {'color': 'rgba(225,225,225, 0.9)'},
name = 'Upper 95% Confidence Interval')
fig.update_layout(template = 'xgridoff',
yaxis = {'title': 'Median Home Price ($USD)'},
xaxis = {'title': 'Year'},
title = {'text': 'Median Home Price vs. Year for {}'.format(selected_city),
'font': {'size': 24}, 'x': 0.5, 'xanchor': 'center'})
return fig
if __name__ == '__main__':
app.run_server(debug = True)
I am trying to update Bokeh DataTable by selecting a plot.Not sure why it's not getting updated?In the code below,source_devon is ColumnDataSource for the plot- I wanted Datatable to get updated when we select a particular portion.Currently DataTable is created(initialization),but it doesn't changes on selection
from bokeh.io import curdoc
from bokeh.layouts import layout,row
from bokeh.models import CDSView,HoverTool,GroupFilter,ColumnDataSource,Button,Select,TextInput,Slider,DataTable,TableColumn,DateFormatter,LinearAxis,Range1d,CustomJS,Rect
from bokeh.plotting import figure,output_file,show
from datetime import datetime, timedelta
from bokeh.client import push_session
import pandas as pd
import numpy as np
TOOLS='pan,wheel_zoom,box_zoom,reset,tap,save,lasso_select,xbox_select'
# Select widget
ccy_options = ['AUDUSD', 'USDJPY']
menu = Select(options=['AUDUSD','USDJPY'], value='AUDUSD')
slider = Slider(start=-1000, end=10000, step=1000, value=-1000, title='Volume Cutoff')
# Function to get Order/Trade/Price Datasets
def get_combined_dataset(src,name):
df = src[(src.CCYPAIR == name)].copy()
return ColumnDataSource(data=df)
# Function to Make Plots
def make_plot(source_order):
x = 'DATE'
y = 'PRICE'
y1 = 'Volume'
size = 10
alpha = 0.5
hover = HoverTool(
tooltips = [
('OrderId', '#ORDER_ID_108'),
('Volume', '#Volume'),
('Price', '#PRICE')
]
)
view1 = CDSView(source=source_order, filters=[GroupFilter(column_name='TYPE',group='ORDER'),GroupFilter(column_name='SIDE',group='B')])
view2 = CDSView(source=source_order, filters=[GroupFilter(column_name='TYPE',group='ORDER'),GroupFilter(column_name='SIDE',group='S')])
view3 = CDSView(source=source_order, filters=[GroupFilter(column_name='TYPE',group='TRADE'),GroupFilter(column_name='SIDE',group='B')])
view4 = CDSView(source=source_order, filters=[GroupFilter(column_name='TYPE',group='TRADE'),GroupFilter(column_name='SIDE',group='S')])
view5 = CDSView(source=source_order, filters=[GroupFilter(column_name='TYPE',group='DevonTrade')])
view6 = CDSView(source=source_order, filters=[GroupFilter(column_name='TYPE',group='Prices')])
plot2 = figure(plot_width=1000, plot_height=300, tools=[hover, TOOLS],
title='Agg. Position Snapshot for Devon',
x_axis_label='Date', y_axis_label='Price',x_axis_type="datetime")
plot = figure(plot_width=1000, plot_height=300,tools=TOOLS,x_axis_type="datetime",title='Order/Execution Snapshot with Price Levels')
plot.circle(x=x,y=y,source=source_order,view=view1,alpha=0.6,color='blue')
plot.circle(x=x,y=y,source=source_order,view=view2,alpha=0.6,color='red')
plot.triangle(x=x,y=y,source=source_order,view=view3,alpha=0.6,color='blue')
plot.triangle(x=x,y=y,source=source_order,view=view4,alpha=0.6,color='red')
plot.line(x=x,y=y,source=source_order,view=view6,color='green')
plot2.line(x=x,y=y1,source=source_order,view=view5,color='blue')
plot.legend.location = 'top_left'
return plot,plot2
def make_table(source):
columns = [
TableColumn(field='DATE', title="DATE", formatter=DateFormatter()),
TableColumn(field='CCYPAIR', title="CCYPAIR"),
TableColumn(field='SIDE', title="SIDE"),
TableColumn(field='PRICE', title="PRICE"),
TableColumn(field='TYPE', title="TYPE"),
TableColumn(field='Volume', title="Volume"),
TableColumn(field='ORDER_ID_108', title="ORDERID"),
]
data_table = DataTable(source=source, columns=columns, width=1000, height=200)
return data_table
def update_plot(attrname, old, new):
newccy = menu.value
newvalue = slider.value
src_data_table = get_combined_dataset(Combined,newccy)
DisplayData.data.update(src_data_table.data)
def update_plot(attrname, old, new):
newccy = menu.value
newvalue = slider.value
src_data_table = get_combined_dataset(Combined,newccy)
DisplayData.data.update(src_data_table.data)
def selection_change(attrname, old, new):
data = get_all_dataset(Combined,menu.value)
selected = DisplayData.selected['1d']['indices']
if selected:
data = data.iloc[selected, :]
update_datatable(data)
def update_datatable(data):
src_data_table = get_combined_dataset(data,menu.value)
s2.data.update(src_data_table.data)
# Input Files
date_today = datetime.now()
days = pd.date_range(date_today, date_today + timedelta(5), freq='D')
Combined1 = {'DATE': days,
'CCYPAIR': ['USDJPY', 'USDJPY', 'USDJPY','USDJPY', 'USDJPY', 'USDJPY'],
'SIDE' : ['B', 'B', 'B','B', 'B', 'B'],
'PRICE': [100.00, 200.00, 300.00,100.00, 200.00, 300.00],
'TYPE' : ['ORDER', 'ORDER', 'ORDER','DevonTrade', 'DevonTrade', 'DevonTrade'],
'Volume': [100, 200, 300, 100, 200, 300],
'ORDER_ID_108': [111,222,333,111,222,333]
}
Combined = pd.DataFrame(Combined1)
DisplayData = get_combined_dataset(Combined,menu.value)
plot,plot2 = make_plot(DisplayData)
menu.on_change('value', update_plot)
plot.x_range = plot2.x_range
s2 = ColumnDataSource(data=dict(DATE=[],CCYPAIR=[],SIDE=[],PRICE=[],TYPE=[],Volume=[],ORDER_ID_108=[]))
columns = [
TableColumn(field='DATE', title="DATE", formatter=DateFormatter()),
TableColumn(field='CCYPAIR', title="CCYPAIR"),
TableColumn(field='SIDE', title="SIDE"),
TableColumn(field='PRICE', title="PRICE"),
TableColumn(field='TYPE', title="TYPE"),
TableColumn(field='Volume', title="Volume"),
TableColumn(field='ORDER_ID_108', title="ORDER_ID_108")
]
data_table = DataTable(source=s2,columns=columns,width=1000, height=200)
layout = layout([menu],
[plot],
[plot2],
[data_table])
curdoc().add_root(layout)
DisplayData.on_change('selected', selection_change)
Your main issue is that the source you are updating does not have the same fields as the source containing the original data. In your callback you are trying to access d2['DATES'] and d2['PRICES'], however you defined the fields as 'x' and 'y'. See below code which has corrected this. I also defined the plotting ranges of the second plot so the data will appear.
from bokeh.io import curdoc
from bokeh.layouts import layout,row
from bokeh.models import HoverTool,ColumnDataSource,Button,Select,TextInput,Slider,DataTable,TableColumn,DateFormatter,LinearAxis,Range1d,CustomJS,Rect
from bokeh.plotting import figure,output_file,show
from datetime import datetime, timedelta
from bokeh.client import push_session
import pandas as pd
import numpy as np
TOOLS='pan,wheel_zoom,box_zoom,reset,tap,save,lasso_select,xbox_select'
# Select widget
menu = Select(options=['AUDUSD','USDJPY'], value='USDJPY')
# Function to get Order/Trade/Price Datasets
def get_order_dataset(src,name):
df = src[(src.CCYPAIR == name) & (src.TYPE == 'ORDER') & (src.SIDE == 'B')].copy()
return ColumnDataSource(data=df)
# Function to Make Plots
def make_plot(source_order):
x = 'DATE'
y = 'PRICE'
size = 10
alpha = 0.5
hover = HoverTool(
tooltips = [
('OrderId', '#ORDER_ID_108'),
('Volume', '#Volume'),
('Price', '#PRICE')
]
)
plot = figure(plot_width=1000, plot_height=300, tools=[hover, TOOLS],
title='Order/Execution Snapshot with Price Levels',
x_axis_label='Date', y_axis_label='Price',x_axis_type="datetime",active_drag="xbox_select")
plot.circle(x=x, y=y, size=size, alpha=alpha, color='blue',
legend='Orders', source=source_order,selection_color="orange")
plot.legend.location = 'top_left'
return plot
def update_plot(attrname, old, new):
newccy = menu.value
src_order = get_order_dataset(Combined,newccy)
source_order.data.update(src_order.data)
date_today = datetime.now()
days = pd.date_range(date_today, date_today + timedelta(2), freq='D')
Combined1 = {'DATE': days,
'CCYPAIR': ['USDJPY', 'USDJPY', 'USDJPY'],
'SIDE' : ['B', 'B', 'B'],
'PRICE': [100.00, 200.00, 300.00],
'TYPE' : ['ORDER', 'ORDER', 'ORDER'],
'Volume': [100, 200, 300],
'ORDER_ID_108': [111,222,333]
}
Combined = pd.DataFrame(Combined1)
source_order = get_order_dataset(Combined,menu.value)
plot = make_plot(source_order)
menu.on_change('value', update_plot)
s2 = ColumnDataSource(data=dict(DATE=[], PRICE=[]))
p2 = figure(plot_width=1000, plot_height=400,
tools="", title="Watch Here",x_axis_type="datetime", y_range=(90,310),x_range=(days[0],days[-1]))
p2.circle('DATE', 'PRICE', source=s2, alpha=0.6, size=10)
source_order.callback = CustomJS(args=dict(s2=s2), code="""
var inds = cb_obj.selected['1d'].indices;
console.log(inds)
var d1 = cb_obj.data;
var d2 = s2.data;
d2['DATE'] = []
d2['PRICE'] = []
for (i = 0; i < inds.length; i++) {
d2['DATE'].push(d1['DATE'][inds[i]])
d2['PRICE'].push(d1['PRICE'][inds[i]])
}
s2.change.emit();""")
layout = layout([menu],
[plot],
[p2])
curdoc().add_root(layout)
from bokeh.io import curdoc
from bokeh.layouts import layout,row
from bokeh.models import CDSView,HoverTool,GroupFilter,ColumnDataSource,Button,Select,TextInput,Slider,DataTable,TableColumn,DateFormatter,LinearAxis,Range1d,CustomJS,Rect
from bokeh.plotting import figure,output_file,show
from datetime import datetime, timedelta
from bokeh.client import push_session
import pandas as pd
import numpy as np
TOOLS='pan,wheel_zoom,box_zoom,reset,tap,save,lasso_select,xbox_select'
# Select widget
ccy_options = ['AUDUSD', 'USDJPY']
menu = Select(options=['AUDUSD','USDJPY'], value='AUDUSD')
slider = Slider(start=-1000, end=10000, step=1000, value=-1000, title='Volume Cutoff')
# Function to get Order/Trade/Price Datasets
def get_combined_dataset(src,name):
df = src[(src.CCYPAIR == name)].copy()
return ColumnDataSource(data=df)
# Function to Make Plots
def make_plot(source_order):
x = 'DATE'
y = 'PRICE'
y1 = 'Volume'
size = 10
alpha = 0.5
hover = HoverTool(
tooltips = [
('OrderId', '#ORDER_ID_108'),
('Volume', '#Volume'),
('Price', '#PRICE')
]
)
view1 = CDSView(source=source_order, filters= [GroupFilter(column_name='TYPE',group='ORDER'),GroupFilter(column_name='SIDE',group='B')])
view2 = CDSView(source=source_order, filters=[GroupFilter(column_name='TYPE',group='ORDER'),GroupFilter(column_name='SIDE',group='S')])
view3 = CDSView(source=source_order, filters=[GroupFilter(column_name='TYPE',group='TRADE'),GroupFilter(column_name='SIDE',group='B')])
view4 = CDSView(source=source_order, filters=[GroupFilter(column_name='TYPE',group='TRADE'),GroupFilter(column_name='SIDE',group='S')])
view5 = CDSView(source=source_order, filters=[GroupFilter(column_name='TYPE',group='DevonTrade')])
view6 = CDSView(source=source_order, filters=[GroupFilter(column_name='TYPE',group='Prices')])
plot2 = figure(plot_width=1000, plot_height=300, tools=[hover, TOOLS],
title='Agg. Position Snapshot for Devon',
x_axis_label='Date', y_axis_label='Price',x_axis_type="datetime")
plot = figure(plot_width=1000, plot_height=300,tools=TOOLS,x_axis_type="datetime",title='Order/Execution Snapshot with Price Levels')
plot.circle(x=x,y=y,source=source_order,view=view1,alpha=0.6,color='blue')
plot.circle(x=x,y=y,source=source_order,view=view2,alpha=0.6,color='red')
plot.triangle(x=x,y=y,source=source_order,view=view3,alpha=0.6,color='blue')
plot.triangle(x=x,y=y,source=source_order,view=view4,alpha=0.6,color='red')
plot.line(x=x,y=y,source=source_order,view=view6,color='green')
plot2.line(x=x,y=y1,source=source_order,view=view5,color='blue')
plot.legend.location = 'top_left'
return plot,plot2
def make_table(source):
columns = [
TableColumn(field='DATE', title="DATE", formatter=DateFormatter()),
TableColumn(field='CCYPAIR', title="CCYPAIR"),
TableColumn(field='SIDE', title="SIDE"),
TableColumn(field='PRICE', title="PRICE"),
TableColumn(field='TYPE', title="TYPE"),
TableColumn(field='Volume', title="Volume"),
TableColumn(field='ORDER_ID_108', title="ORDERID"),
]
data_table = DataTable(source=source, columns=columns, width=1000, height=200)
return data_table
def update_plot(attrname, old, new):
newccy = menu.value
newvalue = slider.value
src_data_table = get_combined_dataset(Combined,newccy)
DisplayData.data.update(src_data_table.data)
def update_plot(attrname, old, new):
newccy = menu.value
newvalue = slider.value
src_data_table = get_combined_dataset(Combined,newccy)
DisplayData.data.update(src_data_table.data)
def selection_change(attrname, old, new):
data = get_all_dataset(Combined,menu.value)
selected = DisplayData.selected['1d']['indices']
if selected:
data = data.iloc[selected, :]
update_datatable(data)
def update_datatable(data):
src_data_table = get_combined_dataset(data,menu.value)
s2.data.update(src_data_table.data)
# Input Files
date_today = datetime.now()
days = pd.date_range(date_today, date_today + timedelta(5), freq='D')
Combined1 = {'DATE': days,
'CCYPAIR': ['USDJPY', 'USDJPY', 'USDJPY','USDJPY', 'USDJPY', 'USDJPY'],
'SIDE' : ['B', 'B', 'B','B', 'B', 'B'],
'PRICE': [100.00, 200.00, 300.00,100.00, 200.00, 300.00],
'TYPE' : ['ORDER', 'ORDER', 'ORDER','DevonTrade', 'DevonTrade', 'DevonTrade'],
'Volume': [100, 200, 300, 100, 200, 300],
'ORDER_ID_108': [111,222,333,111,222,333]
}
Combined = pd.DataFrame(Combined1)
DisplayData = get_combined_dataset(Combined,menu.value)
plot,plot2 = make_plot(DisplayData)
menu.on_change('value', update_plot)
plot.x_range = plot2.x_range
s2 = ColumnDataSource(data=dict(DATE=[],CCYPAIR=[],SIDE=[],PRICE=[],TYPE= [],Volume=[],ORDER_ID_108=[]))
columns = [
TableColumn(field='DATE', title="DATE", formatter=DateFormatter()),
TableColumn(field='CCYPAIR', title="CCYPAIR"),
TableColumn(field='SIDE', title="SIDE"),
TableColumn(field='PRICE', title="PRICE"),
TableColumn(field='TYPE', title="TYPE"),
TableColumn(field='Volume', title="Volume"),
TableColumn(field='ORDER_ID_108', title="ORDER_ID_108")
]
data_table = DataTable(source=s2,columns=columns,width=1000, height=200)
layout = layout([menu],
[plot],
[plot2],
[data_table])
curdoc().add_root(layout)
DisplayData.on_change('selected', selection_change)
I’m trying to replicate the dashboard example here
I got 2 errors:
1) Using the “fileId_from_url” function I get the raw_fileId as empty so that when I try to access it
raw_fileId = re.findall("~[A-z]+/[0-9]+", url)[0][1: ]
I get the error
IndexError: list index out of range
2) If I manually change “/” to “:” in the urls, I can go on. When I try to create the dashboard with the line:
py.dashboard_ops.upload(my_dboard, ‘My First Dashboard with Pythonvv’)
I get the error:
raise exceptions.PlotlyRequestError(message, status_code, content)
3) What if I want to try to run it offline? If I import “import plotly.offline as pyo” I can’t use “pyo.dashboard_ops.upload” anymore.
Thanks in advance.
I add the code below
import plotly.plotly as py
py.sign_in(username='myname', api_key='mypass')
#%%
import plotly.dashboard_objs as dashboard
import IPython.display
from IPython.display import Image
my_dboard = dashboard.Dashboard()
my_dboard.get_preview()
#%%
import plotly.graph_objs as go
import numpy as np
colorscale = [[0, '#FAEE1C'], [0.33, '#F3558E'], [0.66, '#9C1DE7'], [1, '#581B98']]
trace1 = go.Scatter(
y = np.random.randn(500),
mode='markers',
marker=dict(
size='16',
color = np.random.randn(500),
colorscale=colorscale,
showscale=True
)
)
data = [trace1]
url_1 = py.plot(data, filename='scatter-for-dashboard', auto_open=False)
py.iplot(data, filename='scatter-for-dashboard')
#%%
x0 = np.random.randn(50)
x1 = np.random.randn(50) + 2
x2 = np.random.randn(50) + 4
x3 = np.random.randn(50) + 6
colors = ['#FAEE1C', '#F3558E', '#9C1DE7', '#581B98']
trace0 = go.Box(x=x0, marker={'color': colors[0]})
trace1 = go.Box(x=x1, marker={'color': colors[1]})
trace2 = go.Box(x=x2, marker={'color': colors[2]})
trace3 = go.Box(x=x3, marker={'color': colors[3]})
data = [trace0, trace1, trace2, trace3]
url_2 = py.plot(data, filename='box-plots-for-dashboard', auto_open=False)
py.iplot(data, filename='box-plots-for-dashboard')
#%%
import re
def fileId_from_url(url):
"""Return fileId from a url."""
raw_fileId = re.findall("~[A-z]+/[0-9]+", url)[0][1: ]
return raw_fileId.replace('/', ':')
def sharekey_from_url(url):
"""Return the sharekey from a url."""
if 'share_key=' not in url:
return "This url is not 'sercret'. It does not have a secret key."
return url[url.find('share_key=') + len('share_key='):]
fileId_1 = fileId_from_url(url_1)
fileId_2 = fileId_from_url(url_2)
box_a = {
'type': 'box',
'boxType': 'plot',
'fileId': fileId_1,
'title': 'scatter-for-dashboard'
}
text_for_box = ""
box_b = {
'type': 'box',
'boxType': 'text',
'text': text_for_box,
'title': 'Markdown Options for Text Box'
}
box_c = {
'type': 'box',
'boxType': 'plot',
'fileId': fileId_2,
'title': 'box-for-dashboard',
'shareKey': sharekey_from_url(url_2)
}
my_dboard.insert(box_a)
my_dboard.insert(box_b, 'above', 1)
#%%
my_dboard.get_box(1)
my_dboard.get_box(1)['title'] = 'a new title'
my_dboard.get_box(1)
my_dboard.insert(box_a, 'below', 2)
my_dboard['settings']['logoUrl'] = 'https://images.plot.ly/language-icons/api-home/python-logo.png'
my_dboard['settings']['links'] = []
my_dboard['settings']['links'].append({'title': 'Link to Plotly', 'url': 'https://plot.ly/'})
my_dboard['settings']['links'].append({'title': 'Link to Python Website', 'url': 'https://www.python.org/'})
my_dboard['settings']['foregroundColor'] = '#000000'
my_dboard['settings']['backgroundColor'] = '#adcaea'
my_dboard['settings']['headerForegroundColor'] = '#ffffff'
my_dboard['settings']['headerBackgroundColor'] = '#D232C8'
my_dboard['settings']['boxBackgroundColor'] = '#ffffff'
my_dboard['settings']['boxBorderColor'] = '#000000'
my_dboard['settings']['boxHeaderBackgroundColor'] = '#ffffff'
stacked_dboard = dashboard.Dashboard()
text_box = {
'type': 'box',
'boxType': 'text',
'text': 'empty space'
}
for _ in range(5):
stacked_dboard.insert(text_box, 'below', 1)
#%%
stacked_dboard['layout']['size'] = 3000
my_dboard['layout']['first']['first'] = text_for_box
py.dashboard_ops.upload(my_dboard, 'My First Dashboard with Pythonvv')