I am building a dashboard for plotting graphs with an opportunity to exclude outliers by clicking on points on the graph and change the data with interpolated values.
The main idea of this dashboard is to make data preparation faster and easier for people who don’t use Python. Also this dash will be used for simple data visualisation (sort of power BI handmade). And after all iterations a new file with clear data will be written as .csv without outliers.
Working on this i ran into 2 problems:
How to connect imported by dashboard interface data with plot layout.
How to choose points on the graph or choose time period in datePickerRange, delete values and interpolate (scipy.interpolate.interp1d) missing(deleted) values or change them with moving mean (pd.rolling_mean()).
Also I found out that pandas interpolations yields kind of same results, so it will be fine to use it.
There is code block for data parsing:
def parse_contents(contents, filename, date):
content_type, content_string = contents.split(',')
decoded = base64.b64decode(content_string)
try:
if 'csv' in filename:
# Assume that the user uploaded a CSV file
df = pd.read_csv(io.StringIO(decoded.decode('cp1251')), sep = ';' )
elif 'tsv' in filename:
# Assume that the user uploaded a TSV file
df = pd.read_csv(io.StringIO(decoded.decode('utf-8')), sep = '\t')
elif 'xls' in filename:
# Assume that the user uploaded an excel file
df = pd.read_excel(io.BytesIO(decoded))
elif 'xlsx' in filename:
# Assume that the user uploaded a new excel file
df = pd.read_excel(io.BytesIO(decoded))
except Exception as e:
print(e)
return html.Div([
'There was an error processing this file.'
])
return html.Div([
html.H5(filename),
html.H6(datetime.datetime.fromtimestamp(date)),
dash_table.DataTable(
data = df.to_dict('rows'),
columns = [{'name': i, 'id': i} for i in df.columns]),
html.Hr(), # horizontal line
# For debugging, display the raw contents provided by the web browser
html.Div('Raw Content'),
html.Pre(contents[0:10] + '...', style = {
'whiteSpace': 'pre-wrap',
'wordBreak': 'break-all'
})
])
and callback function for input box:
#dashboard.callback(
Output('output-data-upload', 'children'),
[Input('upload-data', 'contents')],
[State('upload-data', 'filename'),
State('upload-data', 'last_modified')])
def update_output(list_of_contents, list_of_names, list_of_dates):
if list_of_contents is not None:
children = [parse_contents(c, n, d) for c, n, d in zip(list_of_contents, list_of_names, list_of_dates)]
return children
This part of code literally was taken from official documentation.
It is fascinating that I can look on uploaded data, but I would like to use column names and date from these columns for plotting the same way I do it in Pandas.
To choose column name I created two dropdown components:
#Create dropdown for X-axis
html.Div([
dcc.Dropdown(
id = 'xaxis-column',
options = [{'label': i, 'value': i} for i in df.columns],
value = 'Xdate')],
style = {'width': '48%', 'display': 'inline-block'}),
#Create dropdown for Y-axis
html.Div([
dcc.Dropdown(
id = 'yaxis-column',
options = [{'label': i, 'value': i} for i in df.columns],
value = 'Yval')],
style = {'width': '48%', 'float': 'right', 'display': 'inline-block'})
And the part of code for graph:
dcc.Graph(id = 'graph')
#dashboard.callback(
Output('graph', 'figure'),
[Input('xaxis-column', 'value'),
Input('yaxis-column', 'value'),
Input('xaxis-type', 'value'),
Input('yaxis-type', 'value'),
Input('XYeardate--slider', 'value')])
def update_graph(xaxis_column_name, yaxis_column_name,
xaxis_type, yaxis_type, Year_value):
dff = df[df['XYeardate'] == Year_value]
return {
'data': [go.Scatter(
x = dff[dff['Xval'] == xaxis_column_name]['Xdate'],
y = dff[dff['Xval'] == yaxis_column_name]['Yval'],
text = dff[dff['Xval'] == yaxis_column_name]['ID'],
mode = 'markers',
marker = {
'size': 10, #was 'size': 15
'opacity': 0.5,
'line': {'width': 0.5, 'color': 'white'}})],
'layout': go.Layout(
xaxis = {
'title': xaxis_column_name,
'type': 'linear' if xaxis_type == 'Linear'},
yaxis = {
'title': yaxis_column_name,
'type': 'linear' if yaxis_type == 'Linear'},
margin = {'l': 40, 'b': 40, 't': 10, 'r': 0},
hovermode = 'closest')}
I can add other parts of code in comments if needed.
Any comments would be appreciated!
Related
I would like to keep the dropdown value in dcc.Store, so it can repeatedly to be call from all the page within the app.py.
The dd2 is come after the dd1 and raditem, which mean the value of dd2 is based on the selected value of dd1 and raditem.
I had tried to store the dd2 in storedd2, however, it is not workable. It can't display the information in page2.py in the table.
This is the code that I currently using. It is not issue if the callback is come from the same page (mean dropdown and table in the same page). However, when it go to multiple page, the raditem in the page1.py will not able to call from page2.py, therefore, need to store the value in dcc.Store only able to recall from other page.
page1.py
dcc.Store(id = 'storedd2', storage_type='session'),
dcc.Dropdown(id='dd1', value= '',
options = [{'label':x, 'value':x}
for x in date_cat],
searchable = True, search_value='',
placeholder= 'DD/MM/YYYY',
clearable=True
),
dcc.Dropdown(id='dd2', value='',
searchable = True, search_value='',
placeholder= 'Please select ...',
clearable=True,
),
dcc.RadioItems(id= 'raditem',
options=[
{'label': ' A', 'value': 'a'},
{'label': ' B', 'value': 'b'},
{'label': ' C', 'value': 'c'},
],
value='a',
)
#callback(
Output('dd2','options'),
Input('dd1', 'value'),
Input('raditem', 'value')
)
def update_dd (dd1, raditem):
if raditem == 'a':
id= df.drop_duplicates(['a'], inplace= False)
relevant_id= id[ df['date'] == dd1]['a'].values.tolist()
id_option= [dict(label=x,value=x)for x in relevant_id]
elif raditem == 'b':
id= df.drop_duplicates(['b'], inplace= False)
relevant_id= id[ df['date'] == dd1]['b'].values.tolist()
id_option= [dict(label=x,value=x)for x in relevant_id]
elif raditem == 'c':
id= df.drop_duplicates(['c'], inplace= False)
relevant_id= id[ df['date'] == dd1]['c'].values.tolist()
id_option= [dict(label=x,value=x)for x in relevant_id]
return id_option
#callback(
Output('storedd2','data'),
Input('dd2', 'value'),
)
def get_data (dd2):
return dd2
page2.py
dash_table.DataTable(id='table',
columns=[
{'name': '', "id": 'header'},
{'name': 'Information', "id": 'info'},
],
)
#callback(
Output('table', 'data'),
Input('dd2', 'value'),
Input('raditem', 'value')
)
def update_table(selection, raditem):
if len (selection) == 0:
return dash.no_update
else:
if raditem == 'a':
dff = df[(df['a'] == selection)]
elif raditem == 'b':
dff = df[(df['b'] == selection)]
elif raditem == 'c':
dff = df[(df['c'] == selection)]
columns = dff[['header','info']]
data= columns.to_dict('records')
return data
dataframe
enter image description here
Expected output:
page1.py
enter image description here
page2.py
enter image description here
Anyone can assist on this?
Or if have any suggestion, please let me know.
I am working on a Dash app and want to include a button/hyperlink to a local html file, however I need to be able to change the html file depending on what search term is input. Below is what I currently have, but I keep getting an error saying the dbc.Button doesn't support 'n-clicks'. I also had an issue with the link immediately being opened when the script was ran. I've never used the Dash Bootstrap components before so I'm not really sure what I need to do to fix this issue.
This is just a snippet of the code so that it wasn't too long
app.layout = html.Div([
html.H1('Gene-NE'),
html.H5('Created by Lauren Kirsch and Dr. Chiquito Crasto'),
html.Label('Search Box'),
dcc.Input(id="search_gene",
type="text",
value='',
placeholder="Type a human gene name",
debounce=True,
minLength=0, maxLength=50,
autoComplete='on',
size='40'),
html.Div([
dcc.Graph(id='mygraph')]),
dcc.RadioItems(
id="vertical_display_toggle",
options=[
{'label': 'Show vertical date bars', 'value': 'show'},
{'label': 'Hide vertical bars', 'value': 'hide'}],
value='hide', # first loading value selected
labelStyle={'display': 'inline-block'}, inputStyle={"margin-left": "8px", "margin-right": "5px"}),
dcc.RadioItems(
id="synonym_display_toggle",
options=[
{'label': 'Show synonyms', 'value': 'show'},
{'label': 'Hide synonyms', 'value': 'hide'}],
value='hide', # first loading value selected
labelStyle={'display': 'inline-block'}, inputStyle={"margin-left": "8px", "margin-right": "5px"}),
html.Div([
dbc.Button("Click Here", id="id-button", className="mr-2"),
html.A(dbc.Nav(dbc.NavItem(dbc.NavLink('Click for PubMedIDs', id='outlink', href='/', target="_blank",
className="nav-link"))))
]),
html.Br(),
html.H6('Texas Tech University Center for Biotechnology and Genomics')])
df = pd.read_csv('list_out.txt', sep='\t', dtype=str)
df = df.transpose().reset_index().rename(columns={'index': 'Date'})
new_header = df.iloc[0]
df = df[1:]
df.columns = new_header
df = df.iloc[0:600]
df = df.set_index('Date')
df = df.iloc[:, ~df.columns.duplicated()]
lookup_df = pd.read_csv('Gene_Lookup.csv', dtype=str)
link = lookup_df.set_index('Approved_Symbol').Linked_Genes.str.split('|').to_dict()
link_date = lookup_df.set_index('Approved_Symbol').Date_Name_Changed.to_dict()
#app.callback(
[Output('mygraph', 'figure'),
Output('outlink', 'children')],
[Input('search_gene', 'value'),
Input('vertical_display_toggle', 'value'),
Input('synonym_display_toggle', 'value'),
Input('id-button', 'n-clicks')])
def update_output(search_gene, vertical_display_user_slct, synonym_display_user_slct, clicks):
if search_gene:
search_gene = search_gene.upper()
syns = link[search_gene]
trace1 = go.Scatter(x=df.index, y=df[search_gene], line_shape='linear', line=dict(color='white'), name=search_gene)
fig = go.Figure()
fig.add_trace(trace1)
if clicks != 0:
return 'f"/assets/{search_gene}.html"'
The main problem is that you've specified n-clicks as input and it needs to be n_clicks instead.
So for clarity, the callback should look more like this:
#app.callback(
[Output("mygraph", "figure"), Output("outlink", "children")],
[
Input("search_gene", "value"),
Input("vertical_display_toggle", "value"),
Input("synonym_display_toggle", "value"),
Input("id-button", "n_clicks"),
],
)
def update_output(
search_gene, vertical_display_user_slct, synonym_display_user_slct, clicks
):
# ...
As far as the link problem goes, I'm not able to reproduce this with what you've shared, but in your callback you have this check:
if clicks != 0:
return 'f"/assets/{search_gene}.html"'
clicks can also be None so make sure this gets handled correctly. Instead you could do something this:
if clicks:
return 'f"/assets/{search_gene}.html"'
This will handle None as well.
I have checked the other similar questions related to the error I am facing. I cannot seem to see why I have been consistently getting this error:
Invalid argument `figure` passed into Graph with ID "graph".
Expected `object`.
Was supplied type `array`.
Value provided:
[
{},
{}
]
This is the following code for the figure I want to update. Essentially, there is a dropdown with a list of names, and the graph should update to the new figure with the topics related to the dropdown value selected.
# main component of dashboard
BODY = dbc.Container(
[
dcc.Dropdown(
id='xaxis-column',
options=[{'label': i, 'value': i}
for i in sorted(user_list['displayName'].unique())],
),
dbc.Card(dcc.Graph(id="graph")),
], className="mt-12")
#app.callback(
Output('graph', 'figure'),
[Input('xaxis-column', 'value')]
)
def update_graph(xaxis_column_name):
print(xaxis_column_name)
df = pd.json_normalize(dataframe['user'])
df['parsedMessage'] = dataframe['parsedMessage']
df['timestamp'] = dataframe['timestamp']
df_one_user = df['displayName'] == xaxis_column_name
dff = df[df_one_user]
messages = list(
dff["parsedMessage"].dropna().values)
if len(messages) < 1:
return {}, {}
text = " ".join(list(messages))
stop_words = ['will', 'reply', 'think', 'http',
'https', 'in reply', 'the us', 'us', 'now'] + list(STOPWORDS)
wc = WordCloud(stopwords=stop_words, max_words=25, max_font_size=80)
wc.generate(text)
word_list, freq_list, fontsize_list, position_list, orientation_list, color_list = [
], [], [], [], [], []
for (word, freq), fontsize, position, orientation, color in wc.layout_:
word_list.append(word)
freq_list.append(freq)
word_list_top = word_list[:10]
freq_list_top = freq_list[:10]
word_df = pd.DataFrame(
{'word_list': word_list_top,
'freq_list': freq_list_top,
})
# print(word_df)
fig = px.bar(word_df, x='word_list', y='freq_list')
return fig
if I don't do the callback, and just hardcode a value for the xaxis_column_name, then it works.
This is my app layout:
app.layout = html.Div(children=[NAVBAR, html.Br(className="my-2"), BODY])
I believe your problem is in return {}, {}. You should return only one dict here.
my sidebar is not callbacking and updating the table with the values from sql.
i want the table to be refreshing in my page
the datatable on app1.py is dead and not updating with new values
any advise?
i believe there is nothing wrong with my apps/app1.py
index.py:
import respective libraries
app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP])
sidebar = html.Div(
[
html.H2("Sidebar", className="display-4"),
html.Hr(),
html.P(
"A simple sidebar layout with navigation links", className="lead"
),
dbc.Nav(
[
dbc.NavLink("Page 1", href="/app1", id="page-1-link"),
dbc.NavLink("Page 2", href="/app2", id="page-2-link"),
],
vertical=True,
pills=True,
),
],
style=SIDEBAR_STYLE,
)
content = html.Div(id="page-content", style=CONTENT_STYLE)
app.layout = html.Div([dcc.Location(id="url"), sidebar, content])
index_page = html.Div([
html.H2(children='my-app-is-running', id='title'),
html.Ul([
html.Li(html.A('page-1', href='app1')),
html.Li(html.A('page-2', href='app2')),
]),
])
# this callback uses the current pathname to set the active state of the
# corresponding nav link to true, allowing users to tell see page they are on
#app.callback([Output(f"page-{i}-link", "active") for i in range(1, 3)], [Input("url", "pathname")],
)
def toggle_active_links(pathname):
if pathname == "/":
# Treat page 1 as the homepage / index
return True, False, False
return [pathname == f"/page-{i}" for i in range(1, 3)]
# Update the index
#app.callback(Output("page-content", "children"), [Input("url", "pathname")])
def render_page_content(pathname):
if pathname in ["/", "/page-1"]:
return index_page
elif pathname == "/app1":
return app1.layout
if __name__ == '__main__':
app.run_server(port=8888,debug=True)
This is the page that is linked to the sidebar. However, i cannot get the udpated datatable values fetched from the sql.
apps\app1.py
import respective libraries
def connectSQLServer(driver, server, db):
connSQLServer = pyodbc.connect(
r'DRIVER={' + driver + '};'
r'SERVER=' + server + ';'
r'DATABASE=' + db + ';'
r'Trusted_Connection=yes;',
autocommit=True
)
return connSQLServer
def getData():
df = pd.DataFrame()
sql_conn = connectSQLServer(
'ODBC Driver 13 for SQL Server', 'DESKTOP\SQLEXPRESS', 'display')
cursor = sql_conn.cursor()
d = {'x': [], 'y': [], 'z': []}
sql = 'select * from dbo.data3'
cursor.execute(sql)
myresult = cursor.fetchall()
for x in myresult:
d['x'].append(x[0])
d['y'].append(x[1])
d['z'].append(x[2])
data = pd.DataFrame(d)
df = df.append(data, ignore_index=True)
return df.to_dict('records')
tblcols = [{'name': 'position', 'id': 'x'},
{'name': 'move', 'id': 'y'}, {'name': 'sync', 'id': 'z'}]
layout = html.Div(
html.Div([
html.H4('Dashboard'),
dash_table.DataTable(
id='table',
data=getData(),
editable=True,
style_header=table_header_style,
columns=tblcols),
dcc.Interval(
id='graph-update',
interval=1*1000
)
])
)
#app.callback(
dash.dependencies.Output('table', 'data'),
[dash.dependencies.Input('graph-update', 'n_intervals')])
def updateTable(n):
return getData()
I'm not sure how you got the app to run without a component with the ID 'graph-update' in the layout, but that's what's missing.
I trimmed out the SQL parts, because I don't have your DB, and put in a dummy dataframe. When I added a dcc.Interval component with the ID 'graph-update', the app ran correctly.
I have a simple database as in the below picture:
and the query looks like:
SELECT
[Date]
,[eNodeBName]
,[Downlinkbandwidth]
,[DownlinkEARFCN]
,[CellName]
,[LocalCellId]
,[PhysicalcellID]
,[LRRCConnReqAtt]
,[RRCSetupSuccessRate]
,[InterFreqSuccessRate4G]
,[IntraRATHOSucccessRate]
,[IntraFreqSuccessRate4G]
,[CellDLMaxThroughputMbps]
,[CellDownlinkAverageThroughputMbps]
FROM [myDB].[dbo].[input]
Now I need to create an interactive chart which depends on inputs like a date picker and drop down list.
As this is the sample GUI I created to figure chart throw this inputs as shown in the below picture:
Now I am creating chart based on the below columns name as in the below picture:
as this is the related query as the below:
SELECT
[Date]
,[CellName]
,[LRRCConnReqAtt]
,[RRCSetupSuccessRate]
,[InterFreqSuccessRate4G]
,[IntraRATHOSucccessRate]
,[IntraFreqSuccessRate4G]
,[CellDLMaxThroughputMbps]
,[CellDownlinkAverageThroughputMbps]
FROM [myDB].[dbo].[input]
So now the X-axis should be the Date column and the y-axis related to those below columns is the KPI columns:
SELECT
[LRRCConnReqAtt]
,[RRCSetupSuccessRate]
,[InterFreqSuccessRate4G]
,[IntraRATHOSucccessRate]
,[IntraFreqSuccessRate4G]
,[CellDLMaxThroughputMbps]
,[CellDownlinkAverageThroughputMbps]
FROM [myDB].[dbo].[input]
So now we have a unique column contains unique values is called CellName, this cell name I want create a simple chart for this unique value based on date columnn and KPI column.
So for example I want to show a line chart for a certain CellName = 2002334 for KPI LRRCConnReqAtt based on data from 27 of December to 9 of January. So I need a chart as the below picture and this is an example chart created in Excel.
and this is my code:
import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
from sqlalchemy import create_engine
import datetime
from datetime import datetime as dt
from dash.dependencies import Input, Output
# connect db
engine = create_engine('mssql+pyodbc://xxxxxx\SMxxxxxARTRNO_EXPRESS/myDB?driver=SQL+Server+Native+Client+11.0')
cursor = engine.raw_connection().cursor()
start = datetime.datetime(2019, 12, 2)
end = datetime.datetime(2019, 12, 15)
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
lte_kpis = pd.read_sql('SELECT * FROM [myDB].[dbo].[input]',
engine)
lte_kpis_raw = pd.read_sql('SELECT LRRCConnReqAtt, RRCSetupSuccessRate, InterFreqSuccessRate4G, IntraRATHOSucccessRate, IntraFreqSuccessRate4G,CellDLMaxThroughputMbps, CellDownlinkAverageThroughputMbps FROM [myDB].[dbo].[input]',
engine)
scale_1 = ['LRRCConnReqAtt']
scale_2 = ['RRCSetupSuccessRate', 'InterFreqSuccessRate4G', 'IntraRATHOSucccessRate', 'IntraFreqSuccessRate4G']
scale_3 = ['CellDLMaxThroughputMbps', 'CellDownlinkAverageThroughputMbps']
pd.set_option('display.max_columns', 500)
pd.set_option('display.width', 1000)
availble_cell = lte_kpis['CellName'].unique()
# availble_cell = lte_kpis.unique(lte_kpis[['Date', 'Site Name', 'Cell CI', 'Cell LAC']].values.ravel('K'))
app.layout = html.Div([
dcc.Dropdown(
id='cell-name-xaxis-column',
options=[{'label': i, 'value': i} for i in availble_cell],
value='2205516'
),
dcc.Dropdown(
id='myColumns',
options=[{'label': col, 'value': col} for col in lte_kpis_raw.columns],
multi=True,
value='LRRCConnReqAtt'
),
dcc.DatePickerRange(
id='my-date-picker-range',
min_date_allowed=dt(1995, 8, 5),
max_date_allowed=dt(2030, 9, 19),
initial_visible_month=dt(2019, 10, 5),
start_date=dt(2019, 10, 1),
end_date=dt(2020, 1, 1)
),
html.Div(id='output-container-date-picker-range'),
dcc.Graph(
style={'height': 300},
id='my-graph'
)
])
#app.callback(
Output('my-graph', 'figure'),
[Input('cell-name-xaxis-column', 'value'),
Input('myColumns', 'value')])
def update_graph(xaxis_column_name, yaxis_column_name, date_value):
dff = lte_kpis[lte_kpis['Date'] == date_value]
return {
'data': [dict(
x=dff[dff['Date'] == xaxis_column_name]['Value'],
y=dff[dff['Date'] == yaxis_column_name]['Value'],
text=dff[dff['Date'] == yaxis_column_name]['CellName'],
mode='line',
line={
'size': 15,
'opacity': 0.5
}
)],
}
if __name__ == '__main__':
app.run_server(debug=True)
Note that I want to put more than one KPI in one chart with different plots....
As the scale values in those KPI are little bit different so I tried to create a three types of objects with columns name scale values as the below code
scale_1 = ['LRRCConnReqAtt']
scale_2 = ['RRCSetupSuccessRate', 'InterFreqSuccessRate4G', 'IntraRATHOSucccessRate', 'IntraFreqSuccessRate4G']
scale_3 = ['CellDLMaxThroughputMbps', 'CellDownlinkAverageThroughputMbps']
and this is the error I found:
TypeError: update_graph() missing 1 required positional argument: 'date_value'
Traceback (most recent call last)
File "C:\Users\mwx825326\PycharmProjects\MyReference\venv\Lib\site-packages\dash\dash.py", line 1337, in add_context
output_value = func(*args, **kwargs) # %% callback invoked %%
TypeError: update_graph() missing 1 required positional argument: 'date_value'
Traceback (most recent call last):
File "C:\Users\mwx825326\PycharmProjects\MyReference\venv\Lib\site-packages\dash\dash.py", line 1337, in add_context
output_value = func(*args, **kwargs) # %% callback invoked %%
TypeError: update_graph() missing 1 required positional argument: 'date_value'
Any assistance appreciated.!!!!
Now this question is solved..
But I need it in more static way ,and the way I have to remove one Drop-down and create a chart based on one Drop-down and Date-Picker instead of 2 Drop-down as the removable drop down is based on Columns in DB in y-axis...
First I created Arrays for every Column should be the y-axis column, as I want to make it static charts for every multi or single Column in one Chart based on another Column or multiple Columns value in database....
as the below code:
SHOW_COLUMNS1 = [
'lrrc_re_est_succ',
'cell_dl_max_throughput'
]
SHOW_COLUMNS2 = [
'interfreq_success_rate_4g',
'intrarat_ho_success_rate'
]
SHOW_COLUMNS3 = [
'rcc_setup_success_rate',
'interfreq_success_rate_4g'
]
SHOW_COLUMNS4 = [
'cell_downlink_average_throughput'
]
after that the connection to the Date-Base
# connect db
engine = create_engine('mssql+pyodbc://xxxxxx\zzzzzz/myDB?driver=SQL+Server+Native+Client+11.0')
cursor = engine.raw_connection().cursor()
lte_kpis = pd.read_sql('SELECT * FROM [myDB].[dbo].[lte_details]', engine)
after that I created a GUI for the interactive Charts and pandas read as the below code:
lte_kpis = pd.read_sql('SELECT * FROM [myDB].[dbo].[lte_details]', engine)
pd.set_option('display.max_columns', 10000)
print(lte_kpis)
lte_kpis.set_index('date', inplace=True)
availble_cell = lte_kpis['cell_name'].unique()
plots = []
app.layout = html.Div([
html.H5(
'Huawei KPI Dashbord'),
html.Label('Choose the "Cell-Name"'),
dcc.Dropdown(
id='cell-name-xaxis-column',
options=[{'label': i, 'value': i} for i in availble_cell],
value= availble_cell[0]
),
html.Label('Choose Date Destination'),
dcc.DatePickerRange(
id='date-picker-range',
min_date_allowed=dt(1995, 8, 5),
max_date_allowed=dt(2030, 9, 19),
initial_visible_month=dt(2019, 10, 5),
start_date=dt(2019, 10, 1),
end_date=dt(2020, 1, 1)
),
html.Div(id='output-container-date-picker-range-%s'),
dcc.Dropdown(
id='yaxis-columns',
options=[{'label': col, 'value': col} for col in SHOW_COLUMNS1],
multi=True,
disabled=True,
value=[SHOW_COLUMNS1[0], SHOW_COLUMNS1[1]]
),
dcc.Graph(
style={'height': 300},
id='my-graph'
),
dcc.Dropdown(
id='yaxis-columns2',
options=[{'label': col, 'value': col} for col in SHOW_COLUMNS2],
multi=True,
disabled=True,
value=[SHOW_COLUMNS2[0], SHOW_COLUMNS2[1]]
),
dcc.Graph(
style={'height': 300},
id='my-graph2'
),
dcc.Dropdown(
id='yaxis-columns3',
options=[{'label': col, 'value': col} for col in SHOW_COLUMNS3],
multi=True,
disabled=True,
value=[SHOW_COLUMNS3[0], SHOW_COLUMNS3[1]]
),
dcc.Graph(
style={'height': 300},
id='my-graph3'
),
dcc.Dropdown(
id='yaxis-columns4',
options=[{'label': col, 'value': col} for col in SHOW_COLUMNS4],
multi=True,
disabled=True,
value=[SHOW_COLUMNS4[0]]
),
dcc.Graph(
style={'height': 300},
id='my-graph4'
),
])
and this is Call-back
#app.callback(
Output(component_id='my-graph2', component_property='figure'),
[Input(component_id='cell-name-xaxis-column', component_property='value'),
Input(component_id='yaxis-columns2', component_property='value'),
Input(component_id='date-picker-range', component_property='start_date'),
Input(component_id='date-picker-range', component_property='end_date')])
def update_graph(cell_name, yaxis_cols, start_date, end_date):
if not isinstance(yaxis_cols, list):
yaxis_cols = [yaxis_cols]
print(yaxis_cols)
print((start_date, end_date))
sql_statement = "SELECT date, %s, %s FROM [myDB].[dbo].[lte_details] WHERE ([cell_name]='%s' AND [date]>='%s' AND [date]<='%s')" \
% (SHOW_COLUMNS2[0], SHOW_COLUMNS2[1], cell_name, start_date, end_date)
df = pd.read_sql(sql_statement, engine)
scatters = []
for col in yaxis_cols:
if col == 'lrrc_conn_req_att':
scatters.append(go.Bar(
x=df['date'],
y=df[col],
mode='lines',
name=col
))
else:
scatters.append(go.Scatter(
x=df['date'],
y=df[col],
name=col
))
figure = {
'data': scatters,
}
return figure
Note that as the previous error is related to the missing of data type in data base when importing the excel file to the data base related to the below Code:
col_dict = {
'date': 'Date',
'enodeb_name': 'eNodeB Name',
'downlink_bandwidth': 'Downlink bandwidth',
...........................
}
LTE_DETAILS_TABLE = 'lte_details'
cols = list(col_dict.keys())
# connect db
engine = create_engine('mssql+pyodbc://xxxxx\xxxxxx/myDB?driver=SQL+Server+Native+Client+11.0')
connection = engine.connect()
meta = MetaData()
ltedetails = Table(
LTE_DETAILS_TABLE, meta,
Column('id', Integer, primary_key=True),
Column(cols[0], Date),
Column(cols[1], String),
Column(cols[2], String),
.................................
)
if engine.dialect.has_table(engine, LTE_DETAILS_TABLE):
ltedetails.drop(engine)
meta.create_all(engine)
lte_df = pd.read_excel(os.path.join(os.path.dirname(__file__), 'input.xlsx'), sheet_name='LTE Details', dtype={
col_dict[cols[0]]: str,
col_dict[cols[1]]: str,
col_dict[cols[2]]: str,
.....................................
})
lte_df['Date'] = pd.to_datetime(lte_df['Date'], errors='coerce')
query = db.insert(ltedetails)
values_list = []
row_count = 1
for i in lte_df.index:
row = lte_df.loc[i]
record = {'id': row_count}
for col in col_dict.keys():
if col == cols[3] or col == cols[4] or col == cols[5] or col == cols[6] or col == cols[7] or col == cols[8]:
record[col] = int(row[col_dict[col]])
elif col == cols[9] or col == cols[10] or col == cols[11] or col == cols[12] or col == cols[13] or col == cols[14]:
record[col] = float(row[col_dict[col]])
else:
record[col] = row[col_dict[col]]
values_list.append(record)
row_count += 1
ResultProxy = engine.execute(query, values_list)
connection.close()
engine.dispose()
So I stuck now the I want to remove the Dropp-down with id ``which called id='yaxis-columns', ...
So If there's any comment about how to improve this code performance and Complete to solve my issue..
I am glad for that.