Align header in Dash DataTable - python

I want to align the header to the left in a Dash DataTable. I use the example code from the Dash DataTable documentation. Then I have implemented the style_header dicitionary as suggested in the DataTable reference.
from dash import Dash, dash_table
import pandas as pd
from collections import OrderedDict
data = OrderedDict(
[
("Date", ["2015-01-01", "2015-10-24", "2016-05-10", "2017-01-10", "2018-05-10", "2018-08-15"]),
("Region", ["Montreal", "Toronto", "New York City", "Miami", "San Francisco", "London"]),
("Temperature", [1, -20, 3.512, 4, 10423, -441.2]),
("Humidity", [10, 20, 30, 40, 50, 60]),
("Pressure", [2, 10924, 3912, -10, 3591.2, 15]),
]
)
df = pd.DataFrame(data)
app = Dash(__name__)
app.layout = dash_table.DataTable(
data=df.to_dict('records'),
columns=[{'id': c, 'name': c} for c in df.columns],
style_header={'textAlign': 'left'},
style_cell={'textAlign': 'left'}
)
if __name__ == '__main__':
app.run_server(debug=True)
I would expect the same behaviour as in style_cell, but it has no effect, the columns are left-aligned and the header is right-aligned. I'm not sure, but it occurs to me since I have updated to Dash 2.1.0. How can I align the header to the left?

The behavior seems to be caused by these styles
.dash-table-container .dash-spreadsheet-container .dash-spreadsheet-inner .column-header-name {
margin-left: auto;
}
As a workaround you could add your own styles to overwrite the above
div.dash-table-container .dash-spreadsheet-container .dash-spreadsheet-inner .column-header-name {
margin-left: unset;
}

Related

Dash datatable width parameter does not work for style_header

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',
},
)

Bar graph with editable dash table

I'm trying to make a bar graph with editable dash table but graph changes for just once time. After changing data in table, graph be updated but not like my expectation.
Below is my sample code:
from dash_table import DataTable
from dash.dependencies import Input, Output
import dash
import dash_html_components as html
import dash_core_components as dcc
import pandas as pd
import plotly.graph_objs as go
raw_data = {'Type': ["Cash", "Credit Card"],
'Rate': [50,50]}
test_df = pd.DataFrame(raw_data)
test_df['id'] = test_df['Type']
test_df.set_index('id', inplace=True, drop=False)
app = dash.Dash(__name__)
app.layout = html.Div(children=[
dash_table.DataTable(
id='table',
data=test_df.to_dict('records'),editable=True,
columns=[
{"name": i, "id": i, "deletable": True, "selectable": True, "hideable": True}
if i == "Type" or i == "Rate"
else {"name": i, "id": i, "deletable": True, "selectable": True}
for i in test_df.columns
],
style_cell={
'minWidth': '0px',
'maxWidth': '180px',
'whiteSpace': 'no-wrap',
'overflow': 'hidden',
'textOverflow': 'ellipsis'},
style_table={'overflowX': 'scroll'},
row_deletable=True
),
dcc.Graph(
id='plot',
style={"max-width": "600px",
"margin": "auto",
"display": "inline-block"})
])
#app.callback(Output('plot', 'figure'),
[Input('table', 'data'),
Input('table', 'columns')])
def update_graph(data, cols):
df = pd.DataFrame(data, columns=[c['name'] for c in cols])
figure_2 = go.Figure(data=[
go.Bar(x=df['Type'],
y=df['Rate'],
width=0.45,
text = df['Rate'],
textposition='inside',
marker_color='indianred')])
return figure_2
if __name__ == '__main__':
app.run_server(port=1211, debug=False)
My first time change, graph looking like this:
But from the second time, graph looking like this:
What should I do to fix this problem.
Actually I read editable docs but I still not get it. The Graph in docs is generated like this:
def display_output(rows, columns):
return {
'data': [{
'type': 'heatmap',
'z': [[row.get(c['id'], None) for c in columns] for row in rows],
'x': [c['name'] for c in columns]
}]
}
I don't know how to apply it for bar graph.
Thank you.
If you put a print statement inside your callback of data you will see on initial load the data is as expected
[{'Type': 'Cash', 'Rate': 50, 'id': 'Cash'}, {'Type': 'Credit Card', 'Rate': 50, 'id': 'Credit Card'}]
Rate holds a numeric value.
But when editing values in the datatable the value could be anything so dash table treats your input as a string and not a number.
So after editing a value in the Rate column data could now look like this
[{'Type': 'Cash', 'Rate': 50, 'id': 'Cash'}, {'Type': 'Credit Card', 'Rate': '200', 'id': 'Credit Card'}]
The value I filled in 200 is now a string in data.
It seems that when both Rate values are string values plotly doesn't know how it should draw the bars anymore.
What you could do is to convert the Rate column of df to numeric.
df['Rate'] = pd.to_numeric(df['Rate'])

Choropleth Plotly Graph not appearing on Dash

I have a csv file with various states, and their scores for some particular dates. It is being plotted correctly in the VSCode Notebook but when I try to display it on Dash, the default map is appearing but there's no colour coding. I have tried changing the dataset and even the display options but it's still the same. Anyone else facing this?
I am attaching my entire Dash code below for reference
#importing libraries
import dash
from dash import Dash, dcc, html, Input, Output
import plotly.express as px
import pandas as pd
app = Dash(__name__)
#-- Import and clean data (importing csv into pandas)
df = pd.read_csv("C:\Data Science\Jupyter_Workspace\Twitter_Sentiment\Data\JSONLs\\final_df.csv")
#print(df[:5]) #printing out a sample to verify if it's correct or not
# Importing the GeoJSON File
import geojson
with open("C:\Data Science\Jupyter_Workspace\Twitter_Sentiment\Dash Deployment\states_india.geojson") as f:
india_states = geojson.load(f)
# ------------------------------------------------------------------------------
# App layout
app.layout = html.Div([
html.H1("Sentiment Timeline for Covid-19 in India 2021-22", style={'text-align': 'center'}),
dcc.Dropdown(id="selected_date",
options=[
{"label": "March 20, 2020", "value": 20200320},
{"label": "March 25, 2020", "value": 20200325},
{"label": "March 27, 2020", "value": 20200327},
{"label": "March 30, 2020", "value": 20200330}],
multi=False,
value=20200320,
style={'width': "40%"}
),
html.Div(id='output_container', children=[]),
html.Br(),
dcc.Graph(id='sentiment_map', figure={})
])
# ------------------------------------------------------------------------------
# Connect the Plotly graphs with Dash Components
#app.callback(
[Output(component_id='output_container', component_property='children'),
Output(component_id='sentiment_map', component_property='figure')],
[Input(component_id='selected_date', component_property='value')]
)
def update_graph(date_selected):
print(date_selected)
print(type(date_selected))
container = "The date chosen by user was: {}".format(date_selected)
dff = df.copy()
dff = dff[dff["date"] == date_selected]
# Plotly Express
fig = px.choropleth_mapbox(
data_frame = dff,
locations = 'state',
geojson = india_states,
range_color=(-1, 1),
color = 'vader_score',
mapbox_style = "carto-positron",
color_continuous_scale = px.colors.diverging.RdBu,
color_continuous_midpoint = 0,
center = {'lat': 24, 'lon': 78},
zoom = 2.85,
labels = {'vader_score': 'Sentiment Score'},
title = "Sentiment Map"
)
return container, fig
# --------------------------------
if __name__ == '__main__':
app.run_server(debug=True)
data sourcing
using publicly available geojson for geometry
generating a data frame of sentiment data for dates in dash app
NB state column corresponds to ID in geojson
import requests
import pandas as pd
import numpy as np
import plotly.express as px
# fmt off
india_states = requests.get("https://raw.githubusercontent.com/Subhash9325/GeoJson-Data-of-Indian-States/master/Indian_States").json()
df = pd.DataFrame({"name":['Andaman and Nicobar', 'Andhra Pradesh', 'Arunachal Pradesh',
'Assam', 'Bihar', 'Chandigarh', 'Chhattisgarh',
'Dadra and Nagar Haveli', 'Daman and Diu', 'Delhi', 'Goa',
'Gujarat', 'Haryana', 'Himachal Pradesh', 'Jammu and Kashmir',
'Jharkhand', 'Karnataka', 'Kerala', 'Lakshadweep',
'Madhya Pradesh', 'Maharashtra', 'Manipur', 'Meghalaya', 'Mizoram',
'Nagaland', 'Orissa', 'Puducherry', 'Punjab', 'Rajasthan',
'Sikkim', 'Tamil Nadu', 'Tripura', 'Uttar Pradesh', 'Uttaranchal',
'West Bengal'],
"state":[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
35]})
df = pd.concat([df.assign(date=d, vader_score=np.random.uniform(-1,1,len(df))) for d in [20200320, 20200325, 20200327, 20200330]])
# fmt on
dash app
the issue as such was not with dash but creation of Plotly Express figure
the data frame state column needs to link to an id in geonjson
featureidkey="properties.ID_1" https://plotly.com/python/mapbox-county-choropleth/#indexing-by-geojson-properties
# importing libraries
import dash
from dash import Dash, dcc, html, Input, Output
import plotly.express as px
import pandas as pd
from jupyter_dash import JupyterDash
# app = Dash(__name__)
app = JupyterDash(__name__)
# ------------------------------------------------------------------------------
# App layout
app.layout = html.Div(
[
html.H1(
"Sentiment Timeline for Covid-19 in India 2021-22",
style={"text-align": "center"},
),
dcc.Dropdown(
id="selected_date",
options=[
{"label": "March 20, 2020", "value": 20200320},
{"label": "March 25, 2020", "value": 20200325},
{"label": "March 27, 2020", "value": 20200327},
{"label": "March 30, 2020", "value": 20200330},
],
multi=False,
value=20200320,
style={"width": "40%"},
),
html.Div(id="output_container", children=[]),
html.Br(),
dcc.Graph(id="sentiment_map", figure={}),
]
)
# ------------------------------------------------------------------------------
# Connect the Plotly graphs with Dash Components
#app.callback(
[
Output(component_id="output_container", component_property="children"),
Output(component_id="sentiment_map", component_property="figure"),
],
[Input(component_id="selected_date", component_property="value")],
)
def update_graph(date_selected):
print(date_selected)
print(type(date_selected))
container = "The date chosen by user was: {}".format(date_selected)
dff = df.copy()
dff = dff[dff["date"] == date_selected]
# Plotly Express
fig = px.choropleth_mapbox(
data_frame=dff,
locations="state",
geojson=india_states,
featureidkey="properties.ID_1",
range_color=(-1, 1),
color="vader_score",
mapbox_style="carto-positron",
color_continuous_scale=px.colors.diverging.RdBu,
color_continuous_midpoint=0,
center={"lat": 24, "lon": 78},
zoom=2.85,
labels={"vader_score": "Sentiment Score"},
title="Sentiment Map",
)
return container, fig
# --------------------------------
if __name__ == "__main__":
# app.run_server(debug=True)
app.run_server(mode="inline")

How to create a draggable plotly object

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)

How to use Callback to update Bar Graph in Dash

Since Dash is a fairly new framework for making interactive web-based graphs, there is not too many information that are specific or detailed for beginners. In my case I need to update a simple bar graph using a callback function.
The data does not render on the browser even though the server runs fine without prompting any errors.
Need help sorting out and understanding why data does not render.
import dash
from dash.dependencies import Output, Event
import dash_core_components as dcc
import dash_html_components as html
import plotly
import plotly.graph_objs as go
app = dash.Dash(__name__)
colors = {
'background': '#111111',
'background2': '#FF0',
'text': '#7FDBFF'
}
app.layout = html.Div( children = [
html.Div([
html.H5('ANNx'),
dcc.Graph(
id='cx1'
)
])
]
)
#app.callback(Output('cx1', 'figure'))
def update_figure( ):
return {
'data': [
{'x': ['APC'], 'y': [9], 'type': 'bar', 'name': 'APC'},
{'x': ['PDP'], 'y': [8], 'type': 'bar', 'name': 'PDP'},
],
'layout': {
'title': 'Basic Dash Example',
'plot_bgcolor': colors['background'],
'paper_bgcolor': colors['background']
}
}
if __name__ == '__main__':
app.run_server(debug=True)
You can use callback in a such way (I create dropdown menu for this):
import dash
from dash.dependencies import Output, Input
import dash_core_components as dcc
import dash_html_components as html
import plotly
import plotly.graph_objs as go
import pandas as pd
app = dash.Dash(__name__)
df = pd.DataFrame({'x': ['APC', 'PDP'], 'y': [9, 8]})
colors = {
'background': '#111111',
'background2': '#FF0',
'text': '#7FDBFF'
}
app.layout = html.Div(children=[
html.Div([
html.H5('ANNx'),
html.Div(
id='cx1'
),
dcc.Dropdown(id='cx2',
options=[{'label': 'APC', 'value': 'APC'},
{'label': 'PDP', 'value': 'PDP'},
{'label': 'Clear', 'value': None}
]
)
])])
#app.callback(Output('cx1', 'children'),
[Input('cx2', 'value')])
def update_figure(value):
if value is None:
dff = df
else:
dff = df.loc[df["x"] == value]
return html.Div(
dcc.Graph(
id='bar chart',
figure={
"data": [
{
"x": dff["x"],
"y": dff["y"],
"type": "bar",
"marker": {"color": "#0074D9"},
}
],
"layout": {
'title': 'Basic Dash Example',
"xaxis": {"title": "Authors"},
"yaxis": {"title": "Counts"},
'plot_bgcolor': colors['background'],
'paper_bgcolor': colors['background']
},
},
)
)
if __name__ == '__main__':
app.run_server(debug=True)
If you write output in your calback function then you need to provide input as well, it can be, slider, date picker or dropdown menu and etc. but in your case you dont need any input and output as your graph is not dynamic in this case. check here https://dash.plot.ly/getting-started-part-2
so in your case it is enough just to put id and figure into dcc.Graph component:
import dash
import dash_core_components as dcc
import dash_html_components as html
app = dash.Dash(__name__)
colors = {
'background': '#111111',
'background2': '#FF0',
'text': '#7FDBFF'
}
app.layout = html.Div( children = [
html.Div([
html.H5('ANNx'),
dcc.Graph(
id='cx1', figure={
'data': [
{'x': ['APC'], 'y': [9], 'type': 'bar', 'name': 'APC'},
{'x': ['PDP'], 'y': [8], 'type': 'bar', 'name': 'PDP'},
],
'layout': {
'title': 'Basic Dash Example',
'plot_bgcolor': colors['background'],
'paper_bgcolor': colors['background']
}}
)
])
]
)
if __name__ == '__main__':
app.run_server(debug=True)

Categories

Resources