I have a Data Table in Dash (python) that works very well. I would like the scroll bar to default to the right - that is, to show the most right information in the data table. The current default is the scroll bar is set to the left. I am using time series data for a finance table, so I want to show the most current year, which is all the way to the right (don't want to make it left) and have the scroll bar set so that its show the right and then you would need to scroll to the left to see the left.
Here is what I have and it works fine except for the issue above:
app = dash.Dash(__name__)
app.layout = dash_table.DataTable(
id='table',
columns=[{"name": i, "id": i} for i in df.columns],
data=df.to_dict('records'),
fixed_columns={'headers': True, 'data': 1},
fixed_rows={'headers': True, 'data': 1},
# style_cell={'textAlign': 'left'},
style_cell={'fontFamily': 'sans-serif', 'fontSize': '12px', 'border': '0px'}, #, 'boxShadow': '10 0'},
style_table={'minWidth': '60%'},
style_cell_conditional=[
{
'if': {'column_id': i},
'textAlign': 'left',
'fontWeight': 'bold'
} for i in ['$ in millions']#, 'C']
],
style_header={
'backgroundColor': 'white',
'fontWeight': 'bold',
'borderBottom': '1px solid black'
},
# style_as_list_view=True,
)
# $ in millions
if __name__ == '__main__':
app.run_server()
If you were making your Dash application using JavaScript, the solution would have been pretty straight forward, unfortunately there is no straight forward answer other than creating 'assets' folder and creating a HTML file with a function to scroll right. The easiest way to tackle this, in my opinion, is to just re-arranging the columns backward by doing df = df.columns[::-1] or by slicing and rearranging the df.
Related
Since I use dash, I have some annoying problems with the style_header parameter of the dash_table.Datatable component.
Indeed, some of them like the colors / background colors work while others like width do not work. It seems that it is linked to the other variable 'fixed_rows' which, when set to true (to make the dashboard header fixed), blocks the width selection.
I've tried with all the versions of dash (from 1.20.0 to the very last one when I write these lines, 2.5.1) and always have this problem.
See below :
With fixed_rows={'headers': True} :
image
With fixed_rows not activated :
image
My code :
from dash import Dash
import dash_bootstrap_components as dbc
import dash_html_components as html
import dash_table
from tools.visual import colors
cols = ['ColumnA', 'ColumnB', 'ColumnC']
app = Dash(external_stylesheets=[dbc.themes.BOOTSTRAP], suppress_callback_exceptions=True)
app.layout = html.Div(children=[
# Dashboard
html.Div(id="table", children=[
dash_table.DataTable(
columns=[{"id": i, "name": i} for i in cols],
style_header={
'backgroundColor': colors['bg_board'],
'color': colors['text_category'],
'fontWeight': 'bold',
'textAlign': 'center'
},
style_cell={
'textAlign': 'center',
'whiteSpace': 'normal',
'height': 'auto',
'width': '200px'
},
style_cell_conditional=
[
{
'if': {'column_id': 'Maturity'},
'backgroundColor': colors['bg_board'],
'color': colors['text_category'],
}
],
style_table={
'overflow': 'auto',
},
fill_width=False,
# fixed_rows={'headers': True},
css=[{"selector": ".show-hide", "rule": "display: none"}],
id='tbl'
)
]),
])
if __name__ == '__main__':
app.run_server(debug=False, host='0.0.0.0', port=5026)
You probably solved your issue but here is my take on it for future reference.
style_cell works for headers and data, style_data works for data cells, style_header works for data.
For a fixed size to work, you need to use the 3 parameters as following:
style_cell={
# all three widths are needed
'minWidth': '75px', 'width': '75px', 'maxWidth': '75px',
},
)
Hi i am coding a Sunburst chart in python Plotly with Dash. Sunburst v1
when i go deeper in the leafs Sunburst v2 in first leaf and update the graph i get back to the top rootSunburst v3 after update.
can i start already in leaf? Or maybe simulate the clicks after the graph updates.
I already got the path, id with clickData. Thanks
Edit:clickData Output I can read the information when i click on Point in the Sunburstgraph. There has to be a way to start the sunburst again at this point right? Added some shortened code.
data_sunburst = pd.DataFrame.from_dict(namedict, orient='index',columns=['name','weight','Art', 'tp', 'impact', 'parent_key', 'child_list'])
app = dash.Dash(__name__) ##Starte Dash
styles = {
'pre': {
'border': 'thin lightgrey solid',
'overflowX': 'scroll'
}
}
app.layout = html.Div([
html.H4(id="title",
style={
'textAlign': 'left'}
),
html.Div([
html.H5("Focus CM"),
dcc.RadioItems(
id='focus_cm',
options=[
{'label': "True", 'value': "True"},
{'label': "False", 'value': "False"}],
value="False"
)]),
html.Div([
html.H5("Show T/B"), #color some areas
dcc.RadioItems(
id='show_tb',
options=[
{'label': "Show", 'value':"True"},
{'label': "Dont", 'value':"False" }],
value="False"
)]),
html.Br(),
dcc.Graph(id='sunburst'),
html.Div([
dcc.Markdown("""
**Click Data**
Click on points in the graph.
"""),
html.Pre(id='click-data', style=styles['pre']),
], className='three columns'),
])
#app.callback(
Output('click-data', 'children'),
Output('title', 'children'),
Input('sunburst', 'clickData'))
def display_click_data(clickData):
click_path = "test"
if clickData:
click_path = clickData["points"][0]["id"]
percentEntry = (clickData["points"][0]).get("percentEntry") ##Show all when returning to root
parent = (clickData["points"][0]).get("parent")
if percentEntry == 1 and parent == "test":
click_path = "test"
title = f"Selected from Sunburst Chart: {' '.join(click_path)}"
return json.dumps(clickData, indent=2), title
#app.callback(
Output('sunburst', 'figure'),
Input('show_tb', 'value'))
def update_graph(show_tb_input):
global focus_cm, show_tb, tp_dict
if show_tb_input == "True":
show_tb = True
else:
show_tb =False
tp_dict = {"bsp": C_BSP, "wm": C_WM}
colors = set_colors_for_sunburst(namedict) ## set color when Show T/B input True;False
fig = go.Figure(go.Sunburst( ## Build fig; Can i build already in Point from clickData?
ids=data_sunburst.index,
labels=data_sunburst.name,
parents=data_sunburst.parent_key,
values=data_sunburst.weight,
branchvalues="total",
marker=dict(colors=colors),
insidetextorientation="auto",
))
fig.update_layout(
grid=dict(columns=2, rows=1),
margin=dict(t=0, l=0, r=0, b=0))
return fig
if __name__ == '__main__':
app.run_server(debug=True, use_reloader=True)
Easy solution:
Sunburst Object has paramenter level:
level – Sets the level from which this trace hierarchy is rendered. Set level to '' to start from the root node in the hierarchy. Must be an “id” if ids is filled in, otherwise plotly attempts to find a matching item in labels.
I created a Dash application to present some data.
I've got a DataTable showing on the front page and I've set pagination configurations for it.
The DataTable is great except for 2 things:
The button in charge of moving to the next pages and back is positioned way off in relation to the table
The beginning and end of the table (the cells) are not showing well when I decrease the monitor size (non responsive)
I've added a picture to help understand these issues:
This is on my wide screen, if I switch to my phone then the beginning of the ID column is not showing and the page navigator buttons are not showing as well.
This is the code I use to create this, the DataTable is wrapped inside the main container div:
import dash_html_components as html
from dash_table import DataTable
...
The code for the datatable:
active = DataTable(id='active-strategies',
columns=[{
"name": col,
"id": col
} for col in dummy_table.columns],
data=dummy_table.to_dict('records'),
page_current=0,
page_size=15,
filter_action="native",
style_table={
'width': '80%',
'margin': 'auto',
'padding': '0 5px',
'overflowX': 'auto',
'overflowY': 'auto',
},
style_cell={
'padding': '0 10px',
'fontSize': '14px',
'textAlign': 'center',
'whiteSpace': 'normal',
},
style_data={},
style_as_list_view=True)
And the div it's wrapped in:
layout1 = html.Div([
...
active,
...
],
style={
'display': 'flex',
'flexDirection': 'column',
'justiyContent': 'center',
'alignItems': 'center',
'margin': 'auto',
'overflow': 'hidden',
'marginBottom': '200px'
})
Adding 'margin-left': '5%', 'margin-right': '5%' and 'width' : '90%' in your html.Div style should fix this issue! Play around with the values, of course.
I have a plotly histogram with a shape in the background. How can I make the background object right/left dragg-able?
import numpy as np
import plotly.graph_objects as go
# generate data
data = np.random.normal(0,10,500)
# plot histogramm
fig = go.Figure()
fig.add_trace(go.Histogram(x=data))
# add shape
fig.add_shape(dict(type="rect", xref="x", yref="paper",
x0=-22, x1=22,
y0=0, y1=1,
fillcolor="Gray", opacity=0.3,
layer="below", line_width=0, editable=True))
current output:
desired output: have the shape-object draggable.
Edit: The background object doesnt have to be a "shape"
Disclaimer: I am not very experienced in Dash, but this was the only way I could implement a movable shape. I relied heavily on this answer by chriddyp in the Plotly Community forum. The parameters of dcc.Graph are pretty similar to go.Figure.
One thing to note is that only when your cursor is very much interior to the shape are you able to drag it, but if you hover anywhere else closer to the borders, clicking and dragging will change your shape's dimensions rather than move it, which may or may not not be the behavior you are after. Anyone who uses Dash regularly- feel free to update/improve upon my answer as needed.
import numpy as np
import json
from textwrap import dedent as d
import dash
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html
# generate data, set seed for reproducibility
np.random.seed(42)
data = np.random.normal(0,10,500)
app = dash.Dash(
__name__,
external_stylesheets=[
'https://codepen.io/chriddyp/pen/dZVMbK.css'
]
)
styles = {'pre': {'border': 'thin lightgrey solid', 'overflowX': 'scroll'}}
app.layout = html.Div(className='row', children=[
dcc.Graph(
id='basic-interactions',
className='six columns',
figure={
'data': [{
'x': data,
'name': 'Trace 1',
'type': 'histogram'
}],
'layout': {
'shapes': [{
'type': 'rect',
'x0': -22,
'x1': 22,
'xref': 'x',
'y0': 0,
'y1': 50,
'yref': 'y',
'fill': 'toself',
'line': dict(
color="Gray",
width=0.5,
),
'fillcolor': 'Gray',
'layer': 'below'
}]
}
},
config={
'editable': True,
'edits': {
'shapePosition': True
}
}
),
])
if __name__ == '__main__':
app.run_server(debug=True)
I’m new to Dash. But I really loved the way it works.
I’m trying to implement a certain live streaming code for stocks which plots the graph by reading it from an external dictionary variable.
I’m sure that I get data continuously. However, this live streaming works perfectly only for 15 minutes and then it stops working. I have to restart the app which I’m not interested in doing so.
Please guide me to solve this.
Also, if I zoom during streaming, it resets my scale because of interval time. How can I fix this ?
Here is my code:
# Import statements
# Importing external python script which is useful in handling the stock data
from StockData import StockData
# dash is an open source graph and dashboard building framework using PlotLy and Flask
import dash
# dcc contains the core graph components
import dash_core_components as dcc
# for javascript and css especially for html components such as id and div
import dash_html_components as html
# for live events
from dash.dependencies import Event
# working with data-frames and datetime series
import pandas as pd
class ChartPlot:
"""
Everything related to plotting chart should be inside this class
Once I initiate the class from the Main.py file, it should start plotting
StockData.data_dictionary has the data
"""
def __init__(self, title="STOCK CHARTS"):
"""
Initialising the dash app
:param title: title of the graph
"""
# Name of the app - stock-tickers
app = dash.Dash('stock-tickers')
# TITLE OF THE APP - THAT WILL BE REFLECTED ON THE TAB
app.title = title
external_css = ["https://fonts.googleapis.com/css?family=Product+Sans:400,400i,700,700i",
"https://cdn.rawgit.com/plotly/dash-app-stylesheets/2cc54b8c03f4126569a3440aae611bbef1d7a5dd/stylesheet.css"]
for css in external_css:
app.css.append_css({"external_url": css,
'modeBarButtonsToRemove': ['sendDataToCloud'], 'displaylogo': False})
def plot_live(self, stock_symbols=StockData.symbol_list, hostname='127.0.0.1', port=5000):
app = self.app
# LAYOUT OF OUR APPLICATION
app.layout = html.Div([
# THE FIRST LINE DESIGN
html.Div([
html.H2('STOCK CHARTS',
# styling can be customised here for title
style={'display': 'inline',
'float': 'left',
'font-size': '2.65em',
'margin-left': '7px',
'font-weight': 'bolder',
'font-family': 'Product Sans',
'color': "rgba(117, 117, 117, 0.95)",
'margin-top': '20px',
'margin-bottom': '0'
})
]),
# DROP DOWN FROM THE AVAILABLE TICKERS
# we are using the stock_symbols from the stock_symbols StockData.symbol_list
dcc.Dropdown(
id='stock-ticker-input',
options=[{'label': s, 'value': s}
for s in stock_symbols],
# DEFAULT VALUE - CAN BE EMPTY AS WELL
value=[stock_symbols[0]],
# INDICATES MULTIPLE SELECTION IS POSSIBLE
multi=True
),
dcc.Checklist(
id='check-list-input',
options=[
{'label': 'High', 'value': 'High'},
{'label': 'Low', 'value': 'Low'}
],
values=['High', 'Low'],
labelStyle={'display': 'inline-block'}
),
# WHERE THE GRAPHS ARE APPEARED
html.Div(id='graphs'),
# INTERVAL FOR UPDATING
dcc.Interval(
id='graph-update',
# 1000 MILLI-SECONDS
interval=1 * 1000
),
], className="container")
# BOOTSTRAP CONTAINER CLASS
# CALL BACK FUNCTION DECORATOR - DEFAULT
#app.callback(
# WHERE THE OUTPUT IS EXPECTED
dash.dependencies.Output('graphs', 'children'),
# WHAT IS THE INPUT FOR THE OUTPUT
[dash.dependencies.Input('stock-ticker-input', 'value'),
dash.dependencies.Input('check-list-input', 'values')],
# ANY SPECIFIC EVENTS - HERE UPDATING BASED ON INTERVAL
events=[Event('graph-update', 'interval')])
def update_graph(symbols, checkers):
"""
This plots the graphs based on the symbol selected
:param symbols: list of available symbols
:return: graphs with high and low values
"""
# Total graphs
graphs = list()
# where all the data is present
data = list()
# running through the selected tickers
for i, symbol in enumerate(symbols):
# StockData has data_dictionary with symbols as keys containing time stamp, high and low data for particular key
data_dictionary = StockData.data_dictionary[symbol]
# Extracting data out of selected data frame
if len(checkers) == 2:
graph_data = [{'x': pd.to_datetime(data_dictionary['Time Stamp']), 'y': data_dictionary['High'],
'type': 'line', 'name': str(symbol) + " High"},
{'x': pd.to_datetime(data_dictionary['Time Stamp']), 'y': data_dictionary['Low'],
'type': 'line', 'name': str(symbol) + ' Low'}]
elif 'High' in checkers:
graph_data = [{'x': pd.to_datetime(data_dictionary['Time Stamp']),
'y': data_dictionary['High'],
'type': 'line', 'name': str(symbol) + " High"}]
elif 'Low' in checkers:
graph_data = [{'x': pd.to_datetime(data_dictionary['Time Stamp']),
'y': data_dictionary['Low'],
'type': 'line', 'name': str(symbol) + ' Low'}]
else:
graph_data = None
# adding to total data
data.extend(graph_data)
# DRAWING THE GRAPH
graphs = [dcc.Graph(
figure={
'data': data,
'layout': {"hovermode": "closest", "spikesnap": "cursor",
"xaxis": {"showspikes": True, "spikemode": "across"},
"yaxis": {"showspikes": True, "spikemode": "across"}}
},
config={'modeBarButtonsToRemove': ['sendDataToCloud'], 'displaylogo': False}
)]
return graphs
app.run_server(debug=True, host=hostname, port=port)
Kindly let me know if I’m doing it wrong anywhere
Based on the Dash documentation snippet
events=[Event('graph-update', 'interval')])
should be:
events=[Event('graph-update', 'n_intervals')])
This seems to be a common hiccup in live streaming dash code... Hope this helps!