dash Dropdown provides either string or list depending on number of selections - plotly-dash

I'm currently working on a stock analysis tool utilizing dash. I have a dropdown populated with the NASDAQ 100 symbols and am attempting to get it to return a line graph with a line for each symbol selected.
With the dropdown, if I have one symbol selected the returned value is a string, if I select multiple it's then a list.
I'm trying to use a callback such as:
#app.callback(
Output(component_id='stock-graph-line', component_property='figure'),
Input(component_id='stock-input', component_property='value'),
suppress_callback_exceptions = True
)
def update_stock_symbol(input_value):
for i in input_value:
fig.append_trace({'x':df.index,'y':df[([i], 'close')], 'type':'scatter','name':'Price [Close]'},1,1)
fig['layout'].update(height=1000, title=input_value, template="plotly_dark")
return fig
However, the for loop does not work with only one symbol selected as it's getting a string, not a list. Is there an option in dash to specify the return type of the callbacks? (Can I force it to pass on the one symbol as a list item?) Or does this have to be handled with if statements testing the type?

I set up a dropdown and it is always returning either None or a list:
dcc.Dropdown(
id='dropdown-id',
options=[
{'label': 'a', 'value': 'a'},
{'label': 'b', 'value': 'b'},
{'label': 'c', 'value': 'c'},
{'label': 'd', 'value': 'd'},
{'label': 'e', 'value': 'e'},
],
multi=True
),
Perhaps yours is set up differently. If that won't work, then just check like this:
def update_stock_symbol(input_value):
if isinstance(input_value, str):
input_value = [input_value]
for i in input_value:
...

Related

Filter one dictionary out of list of dictionaries and extract values of certain keys

Objective:
To filter out of list of dictionaries and extract specific values in that dictionary using python 3.x
Code:
output = data.decode("utf-8")
input = json.loads(output)
for itm in input['items']:
print(itm)
The above code output:
{'name': 'ufg', 'id': '0126ffc8-a1b1-423e-b7fe-56d4e93a80d6', 'created_at': '2022-06-16T04:37:32.958Z'}
{'name': 'xyz', 'id': '194ac74b-54ac-45c6-b4d3-c3ae3ebc1d27', 'created_at': '2022-06-26T10:32:50.307Z'}
{'name': 'defg', 'id': '3744bdaa-4e74-46f6-bccb-1dc2eca2d2c1', 'created_at': '2022-06-26T10:55:21.273Z'}
{'name': 'abcd', 'id': '41541893-f916-426b-b135-c7500759b0b3', 'created_at': '2022-06-24T08:39:39.806Z'}
Now Need to filter only as output for example, I want only dictionary with 'name' as 'abcd'
expected filtered output:
{'name': 'abcd', 'id': '41541893-f916-426b-b135-c7500759b0b3', 'created_at': '2022-06-24T08:39:39.806Z'}
Now, I need to extract only 'name' and 'id' for this 'abcd' into python variable to use it next part of program
Please suggest.
For your situation probably converting into dictionary then filtering would be best.
for itm in input['items']:
itm = dict(itm)
if(itm["name"] == "abcd"):
print(itm["name"],itm["id"])
however, if itm = dict(itm) wouldn't work for your situation, you can use json.loads(itm) then itm = dict(itm).

adding a local html file into a Div in plotly/dash

I created a Dash app. On one tab I have a dropdown and a submit button. In a callback I generate an html file, saved locally, based on quantstats library (reports.html)
I am trying to producing this html within an html.Div but no success so far. All I managed to do is to print out an hyperlink to my local file but not the file itself.
Here is the layout part:
layout = html.Div([
dbc.Container([
dbc.Row([
dbc.Col(html.H1("Reports", className="text-center"), className="mb-5 mt-5")
]),
dbc.Row([
dbc.Col(dcc.Dropdown(id='reports_type',
options=[
{'label': 'YTD', 'value': 1},
{'label': 'ITD', 'value': 2},
],
value=1,
style={'display': 'block'},
)),
dbc.Col(html.Button('Run report', id='reports_submit')),
])
]),
html.Div(id='reports_holder')
])
Here is the callback:
#app.callback(
Output('reports_holder', 'children'),
[
Input('reports_submit', 'n_clicks')
],
[
State('reports_type', 'value')
],
prevent_initial_call=True
)
def produce_report(n_clicks, reports_type):
if n_clicks:
df = some dataframe
if reports_type == 1: #YTD
current_df = df[df.index.year == datetime.date.today().year]
my_pfo = pd.Series(current_df['Close'].values, name='Close', index=current_df.index)
qs.reports.html(my_pfo, "SPY", output='quantstats-tearsheet.html', title='YTD Tearsheet')
else: #ITD
my_pfo = pd.Series(df['Close'].values, name='Close', index=df.index)
qs.reports.html(my_pfo, "SPY", output='quantstats-tearsheet.html', title='ITD Tearsheet')
f = codecs.open('quantstats-tearsheet.html', 'r')
return f
Here is my latest try using the codecs library (this creates an error because the html documents cannot be JSON serializable). If I return f.read() instead then this is not html formated.
As said before I tried html.A instead of html.Div in my layout but this produces only an hyperlink (as expected with html.A). Should I use the property target with html.A but then how do I sepcify that the document should be opened in that same html.A? There must be a straightforward solution to this but I can't find it (most solutions involve opening a local html file into a new browser tab...)
Edit: here is an example of the html report generated via quantstats

plotly-Dash - how to create 3 filters based on dataset columns (drop down list can be multi select)

I am new to Dash, and I don't have knowledge for css and html.
I have a requirement that is to add 3 filters for the sankey chart based on dataCenter, customer and company ID columns with dash library ,type is multi selection dropdown. so I can filter the sankey chart.
The default value for all the 3 filters I need are 'Select All'.
I have refer to some materials on page https://dash.plotly.com/, but due to kind of reason, I am not able to successfully make it.
This is the code for dash part, and i don't know how to add call back for these 3 filters.
app.layout = html.Div([
dcc.Dropdown(
id='my-multi-dataCenter-dropdown',
options=[ {'label': i, 'value': i} for i in dataset['companyID'].unique()] + [{'label': 'Select all', 'value': 'allID'}],
multi=True, placeholder='Please select Data Center'),
dcc.Dropdown(
id='my-multi-customer-dropdown',
options=[{'label': i, 'value': i} for i in dataset['Customer'].unique()] + [{'label': 'Select all', 'value': 'allID'}],
multi=True, placeholder='Please select Customer'),
dcc.Dropdown(
id='my-multi-companyID-dropdown',
options=[{'label': i, 'value': i} for i in dataset['companyID'].unique()] + [{'label': 'Select all', 'value': 'allID'}],
multi=True, placeholder='Please select companyID'),
html.Div(id='dd-output-container'),
dcc.Graph(id='uxrPerfGoalSankey',figure=fig)
])
#app.callback(
Output('dd-output-container', 'children'),
Input('my-multi-dataCenter-dropdown', 'value'),
Input('my-multi-customer-dropdown', 'value'),
Input('my-multi-companyID-dropdown', 'value')
)
def update_output(value):
return 'You have selected "{}"'.format(value)
if __name__ == '__main__':
app.run_server(debug=True)
To add a 'select all' option, you can do something like this:
dcc.Dropdown(
id='my-multi-companyID-dropdown',
options=[
{'label': i, 'value': i} for i in dataset['companyID'].unique()
] + [{'label': 'Select all', 'value': 'allID'],
multi=True, placeholder='Please select companyID')
Then, in your callback, you can check for the 'allID' value, and know that means all values. You'd set a slightly different one for each callback, so you can tell them apart.
Edit: Fix for callback. You need to make sure the number of arguments the function takes matches the number of Input and State values you assign to the callback. The callback should look like this:
#app.callback(
Output('dd-output-container', 'children'),
Input('my-multi-dataCenter-dropdown', 'value'),
Input('my-multi-customer-dropdown', 'value'),
Input('my-multi-companyID-dropdown', 'value')
)
def update_output(data_value, customer_value, company_id_value):
# function body goes here

Dash dropdown navigation

I'm trying to create an interactive menu in a Dash dashboard using a simple Dropdown element. The idea would simply to change the url pathname whenever the value in the Dropdown element changes. I've looked around how to manage that with a callback and couldn't find how to properly do that. Could you please help me on that? Cheers.
import dash_html_components as html
import dash_core_components as dcc
def Header(app):
return html.Div([get_header(app)])
def get_header(app):
logo = html.A(
html.Img(
src=app.get_asset_url("logo.jpeg"),
className="logo",
),
href="google.com",
)
dropdown = dcc.Dropdown(
options=[
{'label': 'Overview', 'value': 'Overview'},
{'label': 'Details', 'value': 'Iteration 1'},
{'label': 'Raw Data', 'value': 'Raw Data'},
],
value='Overview',
)
ddcontainer = html.Div(
[dropdown],
id="dd-container"
)
header = html.Div([logo, ddcontainer])
return header

How to extract certain information from a string and create a json object in python

I made a get request to a website and parsed it using BS4 using 'Html.parser'. I want to extract the ID, size and availability from the string. I have parsed it down to this final string:
'{"id":706816278547,"parent_id":81935859731,"available":false,
"sku":"665570057894","featured_image":null,"public_title":null,
"requires_shipping":true,"price":40000,"options":["S"],
"option1":"s","option2":"","option3":"","option4":""},
{"id":707316252691,"parent_id":81935859731,"available":true,
"sku":"665570057900","featured_image":null,"public_title":null,
"requires_shipping":true,"price":40000,"options":["M"],
"option1":"m","option2":"","option3":"", "option4":""},
{"id":707316285459,"parent_id":81935859731,"available":true,
"sku":"665570057917","featured_image":null,"public_title":null,
"requires_shipping":true,"price":40000,"options":["L"],
"option1":"l","option2":"","option3":"","option4":""},`
{"id":707316318227,"parent_id":81935859731,"available":true,`
"sku":"665570057924","featured_image":null,"public_title":null,
"requires_shipping":true,"price":40000,"options":["XL"],
"option1":"xl","option2":"","option3":"","option4":""}'
I also tried using the split() method but I get lost and im unable to extract the needed information without creating a cluttered list and getting lost.
I tried using json.loads() so i could just extract the information needed by calling the key and value pairs but i get the following error
final_id =
'{"id":706816278547,"parent_id":81935859731,"available":false,
"sku":"665570057894","featured_image":null,"public_title":null,
"requires_shipping":true,"price":40000,"options":["S"],
"option1":"s","option2":"","option3":"","option4":""},
{"id":707316252691,"parent_id":81935859731,"available":true,
"sku":"665570057900","featured_image":null,"public_title":null,
"requires_shipping":true,"price":40000,"options":["M"],
"option1":"m","option2":"","option3":"", "option4":""},
{"id":707316285459,"parent_id":81935859731,"available":true,
"sku":"665570057917","featured_image":null,"public_title":null,
"requires_shipping":true,"price":40000,"options":["L"],
"option1":"l","option2":"","option3":"","option4":""},`
{"id":707316318227,"parent_id":81935859731,"available":true,`
"sku":"665570057924","featured_image":null,"public_title":null,
"requires_shipping":true,"price":40000,"options":["XL"],
"option1":"xl","option2":"","option3":"","option4":""}'
find_id = json.loads(final_id)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/anaconda3/lib/python3.7/json/__init__.py", line 348, in loads
return _default_decoder.decode(s)
File "/anaconda3/lib/python3.7/json/decoder.py", line 340, in decode
raise JSONDecodeError("Extra data", s, end)
json.decoder.JSONDecodeError: Extra data: line 1 column 233 (char 232)
I want to create a json object for each ID and Size and if that size is available or not.
Any help is welcomed. Thank you.
First thats not a valid json info
second, json.loads works for files, so a file containing this info will solve the issue because null in json equal None in python so json.load you can say translate a json file so python understand it, so
import json
with open('sof.json', 'r') as stackof:
final_id = json.load(stackof)
print(final_id)
will output
[{'id': 706816278547, 'parent_id': 81935859731, 'available': 'false', 'sku': '665570057894', 'featured_image': None, 'public_title': None, 'requires_shipping': True, 'price': 40000, 'options': ['S'], 'option1': 's', 'option2': '', 'option3': '', 'option4': ''}, {'id': 707316252691, 'parent_id': 81935859731, 'available': True, 'sku': '665570057900', 'featured_image': None, 'public_title': None, 'requires_shipping': True, 'price': 40000, 'options': ['M'], 'option1': 'm', 'option2': '', 'option3': '', 'option4': ''}, {'id': 707316285459, 'parent_id': 81935859731, 'available': True, 'sku': '665570057917', 'featured_image': None, 'public_title': None, 'requires_shipping': True, 'price': 40000, 'options': ['L'], 'option1': 'l', 'option2': '', 'option3': '', 'option4': ''}, {'id': 707316318227, 'parent_id': 81935859731, 'available': True, 'sku': '665570057924', 'featured_image': None, 'public_title': None, 'requires_shipping': True, 'price': 40000, 'options': ['XL'], 'option1': 'xl', 'option2': '', 'option3': '', 'option4': ''}]
i made all of them divided into array, so now if you print the first id you should write
print(final_id[0]['id'])
output:
706816278547
Tell me in the comments if that helped you,
btw click on >> sof.json to see sof.json