I'm trying to create a Dash app that must:
Read a csv file and convert it to a dataframe
Subset this dataframe according to the user's choices (radio buttons,...)
Generate the subseted dataframe in a csv file
The issue is I can't subset the dataframe as I would like.
Let's imagine I got a data frame gas3 with a variable Flag. Here is a part of my code:
import dash
import dash_core_components as dcc # Graphs
import dash_html_components as html # Tags
from dash.dependencies import Input, Output, Event, State
from pandas_datareader import DataReader
import time
import pandas as pd
import plotly
import plotly.graph_objs as go
from collections import deque
import random
import os
import pandas as pd
import glob
import numpy as np
import statistics
from datetime import *
from pytz import *
import dash_table_experiments as dte
import io
from flask import send_file
import flask
import urllib.parse
# Import df
gas3 = pd.read_csv("D:/Path/gas3.csv", sep=';')
gas3['Date_Local_Time'] = pd.to_datetime(gas3['Date_Local_Time'], format='%Y/%m/%d %H:%M') # Conversion de la variable en type "date heure"
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets) # Starting application
app.layout = html.Div(children=[
# Radio buttons
html.Div([
html.Label("Sélectionnez la valeur du Flag que vous souhaitez :",
htmlFor='radioflag',
),
html.Br(),
html.Br(),
dcc.RadioItems(
id='radioflag',
options=[
{'label': 'Flag 0', 'value': 'Flag0'},
{'label': 'Flag 1', 'value': 'Flag1'},
{'label': 'Flag 3', 'value': 'Flag3'},
{'label': 'Chambre à flux', 'value': 'CAF'}
]
),
html.Br(),
]),
# Download button
html.Div(id='table'),
html.A(
'Download Data',
id='download-link',
download="rawdata.csv",
href="",
target="_blank"
)
])
### Subset function
def filter_data(flag):
gas_genere = gas3.copy()
if flag == 'Flag0':
gas_genere = gas_genere[gas_genere['Flag']==0]
return gas_genere
else:
return gas_genere[0:4]
# Callback
#app.callback(
Output('download-link', 'href'),
[Input('radioflag', 'value')])
def update_download_link(flag):
gas_genere = filter_data(flag)
csv_string = gas_genere.to_csv(index=False, encoding='utf-8', sep=';')
csv_string = "data:text/csv;charset=utf-8,%EF%BB%BF" + urllib.parse.quote(csv_string)
return csv_string
if __name__ == '__main__':
app.run_server(debug=True)
I found out the issue but I don't know how to fix it. If I change my filter_data function to (I just added [0:2] to the first return gas_genere) :
def filter_data(flag):
gas_genere = gas3.copy()
if flag == 'Flag0':
gas_genere = gas_genere[gas_genere['Flag']==0]
return gas_genere[0:2]
else:
return gas_genere[0:4]
The app works well! If I check "Flag 0", gas_genere[0:2] will be generated. Else, gas_genere[0:4] will be generated.
But if I keep it like in my original code, I can check "Flag 1", "Flag 3", "Chambre à flux" or don't check any button, it would work and generate gas_genere[0:4]. But if I check "Flag 0", instead of returning gas_genere, I would not get a csv file, but would get an error: "téléchargement Echec - Erreur réseau." which in English should be "Download Failed - Network Error".
I tryed to generate my dataframe gas_genere = gas3[gas3['Flag']==0] in Python and it got 14299 rows and 43 columns.
Is my dataframe too large? If so, what should I do?
Thank you!
Related
I'm pretty new to Dash. I created two dashboards that read from two different dataframes. They work well individually. I would like to merge them in a single one, giving the possibility to the user to access them using a dropdown menu.
I would like to also add a button which (when clicked) returns a function.
Those are the two dashboards:
first one:
import pandas as pd
df1 = pd.read_csv('/df1.csv')
# Import libraries
from dash import Dash, html, dcc, Input, Output
import pandas as pd
import plotly.express as px
# Create the Dash app
app = Dash()
# Set up the app layout
options_dropdown = dcc.Dropdown(options=df1['options'].unique(),
value='wordcount')
app.layout = html.Div(children=[
html.H1(children='offensive/non offensive username activity dashboard'),
options_dropdown,
dcc.Graph(id='df1')
])
# Set up the callback function
#app.callback(
Output(component_id='df1', component_property='figure'),
Input(component_id=options_dropdown, component_property='value')
)
def update_graph(sel_option):
filtered_options = df1[df1['options'] == sel_option]
bar_fig = px.bar(filtered_options,
x= "user", y = "value",
color='user',
color_discrete_map={
'off': '#d62728',
'non_off': 'green'},
title=f' average {sel_option}',
width=500, height=500)
return bar_fig
print(df1)
# Run local server
if __name__ == '__main__':
app.run_server(debug=True)
second one:
import pandas as pd
df2 = pd.read_csv('/df2.csv')
# Import libraries
from dash import Dash, html, dcc, Input, Output
import pandas as pd
import plotly.express as px
# Create the Dash app
app = Dash()
# Set up the app layout
options_dropdown = dcc.Dropdown(options=df2['options'].unique(),
value='wordcount')
app.layout = html.Div(children=[
html.H1(children='offensive/non offensive username activity dashboard'),
options_dropdown,
dcc.Graph(id='df2')
])
# Set up the callback function
#app.callback(
Output(component_id='df2', component_property='figure'),
Input(component_id=options_dropdown, component_property='value')
)
def update_graph(sel_option):
filtered_options = df2[df2['options'] == sel_option]
line_fig = px.line(filtered_options,
x= "Week_Number", y = "value",
color='offensive',
color_discrete_map={
1: '#d62728',
0: 'green'},
title=f' average {sel_option}')
return line_fig
print(df2)
# Run local server
if __name__ == '__main__':
app.run_server(debug=True)
and this is the function I want to implement pressing a button:
sentences = []
df3 = pd.read_csv('/df3.csv')
def cool_function():
ext = rd.randint(0,len(df3.offensive))
return rd.choice(sentences).format(df3.author[ext], "", df3.text[ext])
How do I merge those three elements in a single dashboard?
I'm trying to make a dash table based on input data but I'm stucking in add more rows to add new inputs. Actually I read this docs and I know that I can directly input in dash table but I want to update dash table from input.
Below is my code:
import pandas as pd
import numpy as np
from datetime import datetime as dt
import plotly.express as px
import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output, State
import dash_table
import dash_bootstrap_components as dbc
from dash_extensions import Download
from dash_extensions.snippets import send_data_frame
import glob
import os
from pandas.tseries.offsets import BDay
import plotly.graph_objects as go
app = dash.Dash(__name__)
MD23 = pd.DataFrame({'Number':[],
'PW':[],
'Name 1':[],
'Name 2':[],
'Email':[],
'Web':[],
'Abc':[]})
# ------------------------------------------------------------------------
input_types = ['number', 'password', 'text', 'tel', 'email', 'url', 'search']
app.layout = html.Div([
html.Div([
dcc.Input(
id='my_{}'.format(x),
type=x,
placeholder="insert {}".format(x), # A hint to the user of what can be entered in the control
minLength=0, maxLength=50, # Ranges for character length inside input box
autoComplete='on',
disabled=False, # Disable input box
readOnly=False, # Make input box read only
required=False, # Require user to insert something into input box
size="20", # Number of characters that will be visible inside box
) for x in input_types
]),
html.Br(),
html.Button('Add Row',id='add_row',n_clicks=0),
dbc.Row([
dbc.Col([html.H5('List',className='text-center'),
dash_table.DataTable(
id='table-container_3',
data=[],
columns=[{"name":i_3,"id":i_3,'type':'numeric'} for i_3 in MD23.columns],
style_table={'overflow':'scroll','height':600},
style_cell={'textAlign':'center'},
row_deletable=True,
editable=True)
],width={'size':12,"offset":0,'order':1})
]),
])
#app.callback(Output('table-container_3', 'data'),
[Input('my_{}'.format(x),'value')for x in input_types])
def update_data(selected_number, selected_pw,
selected_text, selected_tel,
selected_email,selected_url,
selected_search):
data = pd.DataFrame({'Number':[selected_number],
'PW':[selected_pw],
'Name 1':[selected_text],
'Name 2':[selected_tel],
'Email':[selected_email],
'Web':[selected_url],
'Abc':[selected_search]})
return data.to_dict(orient='records')
# ------------------------------------------------------------------------
if __name__ == '__main__':
app.run_server(debug=False)
I tried to add rows as below but it's not worked:
#app.callback(
Output('table-container_3', 'data'),
Input('add_row', 'n_clicks'),
State('table-container_3', 'data'),
State('table-container_3', 'columns'))
def add_row(n_clicks, rows, columns):
if n_clicks > 0:
rows.append()
return rows
I really need suggestions to solve this problem. Thank you so much.
tran
Try to replace your callback with this callback:
#app.callback(
Output('table-container_3', 'data'),
Input('add_row', 'n_clicks'),
[State('table-container_3', 'data'),
State('table-container_3', 'columns')]+
[State('my_{}'.format(x), 'value') for x in input_types])
def add_row(n_clicks, rows, columns, selected_number, selected_pw,
selected_text, selected_tel,
selected_email, selected_url,
selected_search):
if n_clicks > 0:
rows.append({c['id']: r for c,r in zip(columns, [selected_number, selected_pw, selected_text, selected_tel, selected_email, selected_url, selected_search])})
return rows
New to Dash so bear with.
I have a websocket connection that streams forex data to my console; price, high, low, symbol etc.
I'd like to have that information displayed on a dashboard that is easily viewable, instead of everything being printed to my console.
The issue i face is the data only updates on page refresh, when i'd like it to update as it is received, on the dashboard.
This is my code to connect to the websocket and create the dashboard:
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly
from dash.dependencies import Input, Output, State
import fxcmpy
import pandas as pd
import datetime as dt
import time
con = fxcmpy.fxcmpy(access_token = "1111111111111111111111111111111111111111111111212", log_level = 'error')
currenc = ["AUD/CAD", "AUD/CHF", "AUD/JPY", "AUD/NZD", "AUD/USD", "CAD/CHF", "CAD/JPY", "CHF/JPY", "EUR/AUD", "EUR/CAD", "EUR/CHF", "EUR/GBP", "EUR/JPY", "EUR/NZD", "EUR/TRY", "EUR/USD", "GBP/AUD", "GBP/CAD", "GBP/CHF", "GBP/JPY", "GBP/NZD", "GBP/USD", "NZD/CAD", "NZD/CHF", "NZD/JPY", "NZD/USD", "USD/CAD", "USD/JPY"]
app = dash.Dash(__name__)
def print_data(data, dataframe):
t = pd.to_datetime(int(data['Updated']), unit='ms')
price = data['Rates'][0]
symbol = data['Symbol']
app.layout = html.Div([
dcc.Textarea(
id='textprice',
value=(str(price)),
style={'width': '100%', 'height': 300},
),
dcc.Textarea(
id='textsymbol',
value=(str(symbol)),
style={'width': '100%', 'height': 300},
),
html.Div(id='textarea-example-output', style={'whiteSpace': 'pre-line'})
])
if __name__ == '__main__':
for i in currenc:
con.subscribe_market_data(i, (print_data,))
app.run_server(debug=True)
The dashboard contains two text boxes, one for price, the other for symbol. I'd like to be able to have the dashboard open and those values update automatically.
Any help will be appreciated,
What you need is the Interval component. Set up the dcc.Interval for whatever time period you want, and use it as the input to a callback function. The output from that function will be the text boxes with the data you want to refresh each time the interval updates. Very basically:
app.layout = html.Div([
...
dcc.Interval(id='my-interval', interval=5000), # one tick each 5 seconds
html.Div(id='my-output', children=[]),
...
])
#app.callback(Output('my-output', 'children'),
[Input('my-interval', 'n_intervals')])
def callback_func(interval):
# make your calls to get the data
return [html.Div([
# the data content in here
])
When I run the code i get the graph but the graph is not getting updated i am calling the data from my sql laptop sql management studio.
Kindly let me know what needs to be done the X axis contains date and time and Y axis contains data in numeric form which is getting updated automatically
Code:
import pandas as pd
import pyodbc
import numpy as np
server ='LAPTOP-OO3V36UA\SQLEXPRESS'
db='addy'
conn=pyodbc.connect('DRIVER={SQL Server}; SERVER=' +server + ';DATABASE=' + db +
';Trusted_connection=yes')
sql="""
SELECT * FROM Summry
"""
df=pd.read_sql(sql ,conn)
import dash
from dash.dependencies import Output, Input
import dash_core_components as dcc
import dash_html_components as html
from random import random
import plotly
app = dash.Dash(__name__)
app.layout = html.Div([
dcc.Graph(id='live-update-graph-scatter', animate=True),
dcc.Interval(
id='interval-component',
interval=1*1000
)
])
#app.callback(Output('live-update-graph-scatter', 'figure'),
[Input('interval-component', 'interval')])
def update_graph_scatter():
df=pd.read_sql(sql ,conn)
trace1=go.Scatter(
y=df['ACL'],
x = df['DateandnTime'],
mode='lines',
name='ACL'
)
layout = go.Layout(
title='Daily Monitoring'
)
return {'data': trace1, 'layout': layout}
if __name__ == '__main__':
app.run_server()
You've set your callback's input to
Input('interval-component', 'interval')
But you want
Input('interval-component', 'n_intervals')
The interval property sets how frequently n_intervals gets updated. The change in n_intervals is what can be used to trigger the callback.
Here's the documentation: https://dash.plotly.com/dash-core-components/interval
I try to make an interactive dashboard using dash from plotly. I am a beginner in it therefore I used an example to do it.
The code should upload different data files from a certain folder and plot a histogram based on a certain column. The name of each file looks like "30092017ARB.csv" (date + ARB.csv). The code loops over all file names in the data-folder and print the name of files in a drop-down bottom. After selecting the name of file it should be uploaded and plot a histogram. I wrote the following code:
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
import pandas as pd
#
from os import listdir
from os.path import isfile, join
import numpy as np
#
mypath='/Users/Python/BeN_/data/'
onlyfiles = [f for f in listdir(mypath) if isfile(join(mypath, f))]
app = dash.Dash()
app.layout = html.Div([
html.H2("Ausfallsreport"),
html.Div(
[
dcc.Dropdown(
id="dataFH",
options=[{
'label': i,
'value': i
} for i in onlyfiles],
value=" "),
],
style={'width': '25%',
'display': 'inline-block'}),
dcc.Graph(id='Mygraph'),
])
#app.callback(
dash.dependencies.Output('Mygraph', 'figure'),
[dash.dependencies.Input('dataFH', 'value')])
def update_graph(dataFH):
df = pd.read_csv(mypath+dataFH, delimiter=';',encoding='cp1252')
# aggregate
dfagg = df.groupby('Bestand', as_index=False).agg({'MW': 'sum'})
# make strings for x-axis
x=["BE-"+s for s in[str(s) for s in [int(x) for x in dfagg.iloc[:,0].tolist()]]]
y=dfagg.ix[:,1].tolist()
trace = go.Bar(x=x, y=y, name='Declined')
return {
'data': [trace],
'layout':
go.Layout(
title='Customer Order Status for {}'.format(dataFH),
barmode='bar',
yaxis=dict(tickformat=".2%"))
}
if __name__ == '__main__':
app.run_server(debug=True)
I get the following under http://127.0.0.1:8050/ .
The problem is that I do not get any Bar chart. Could someone help me to figure out why.
In case you haven't figured it out yet, the issue is that when a user initially connects, it triggers your callback. And you're setting the initial value of dropdown to
dataFH=" "
which causes
df = pd.read_csv(mypath+dataFH ...
to throw an error because that file doesn't exist.
Different ways to fix this, but one way is to check if mypath+dataFH is a file within your callback and return an empty list for the trace if it's not a file:
def update_graph(dataFH):
if isfile(mypath+dataFH):
df = pd.read_csv(mypath+dataFH, delimiter=';',encoding='cp1252')
# aggregate
dfagg = df.groupby('Bestand', as_index=False).agg({'MW': 'sum'})
# make strings for x-axis
x=["BE-"+s for s in[str(s) for s in [int(x) for x in dfagg.iloc[:,0].tolist()]]]
y=dfagg.ix[:,1].tolist()
trace = go.Bar(x=x, y=y, name='Declined')
else:
trace=[]
return {
'data': [trace],
'layout':
go.Layout(
title='Customer Order Status for {}'.format(dataFH),
barmode='bar',
yaxis=dict(tickformat=".2%"))
}