Python Dash resizing candlesticks - python

I've been trying to create a candlestick graph that shows the prices of NASDAQ and moving average on it, which has been a partial success:
import dash
from dash.dependencies import Output, Input
import dash_core_components as dcc
import dash_html_components as html
import plotly
import random
import plotly.graph_objs as go
import yfinance as yf
import plotly.express as px
import datetime as dt
from datetime import datetime
from metody import metody
import time
import pandas as pd
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
NASDAQ = pd.read_excel(r'file.xlsx')
app = dash.Dash(external_stylesheets=external_stylesheets)
fig = go.Figure(data=go.Candlestick(
open=NASDAQ['Open'],
close=NASDAQ['Close'],
low=NASDAQ['Low'],
high=NASDAQ['High'],
))
close = NASDAQ['Close']
open = NASDAQ['Open']
srednia = metody.generateMovingAverage(NASDAQ['Close'], 3)
fig.add_trace(
go.Scatter(
y=srednia
)
)
app.layout = html.Div([
html.H1(
children="This is a chart of {}".format("NASDAQ"),
style={
'text-align': 'center'
}
),
dcc.Graph(
id='candles',
animate=True,
figure=fig,
),
dcc.Interval(
id='update',
interval=1000
)
])
app.run_server(debug=True)
unfortunately however when I'm trying to zoom the results, the candles do not upscale so that it's readable:
My question is: how do I deal with that? I'd love my chart to be nicely interactive (meaning the user can adjust the period and the candles are as big as it fits to the size of the chart).
PS: I'm really new to Dash, so if you've got any comments on my code or you know something I've done the wrong way round, please tell me :)

You need to get this into your code somewhere (upon zoom trigger):
fig.update_yaxes(range=[minY, maxY])
with minY and maxY being chosen from a downselection of your results (and rounded down and up respectively to look a bit better)
But I don't see where your zoom is being done - I assume you aren't using the plotly default but instead closing in using the lower summary bar?
You might have to dive in to the .css I'm afraid - or maybe you can insert additional lines into it before passing it to dash.Dash()

Related

How to obtain Click Event Coordinate Data on Plotly Dash Graph in Python?

I've tried navigating around the web for a solution to this problem, but have had no luck. The closest solution I found was this, however, it's in R and I've been trying to look for a solution in Python for this these past twos days.
I've already messed with Plotly Dash's documentation here on Interactive Graphing and the clickData and hoverData seems to only output coordinate data on actual data points on the graph that are clicked/hovered over on. My goal is obtain a pair of x,y coordinate through two mouse clicks on the graph, so that I am able to draw a line on the graph using that pair of coordinates. However, it seems Plotly's Dash Interactive Graphing is limited in its ability to provide mouse coordinate data that are not on actual data points. Is there any work around to this or an obvious solution / part of the documentation that I missed?
you can create an additional trace of transparent points that are scattered uniformly across the figure
then it's a simple case of using clickData callback
full code below
import numpy as np
import pandas as pd
import plotly.express as px
import math, json
import dash
from dash.dependencies import Input, Output, State
from jupyter_dash import JupyterDash
GS = 100
fig = px.line(
x=np.linspace(0, 1, 300), y=(np.sin(np.linspace(0, math.pi * 3, 300)) / 2) + 0.5
).add_traces(
px.scatter(
x=np.repeat(np.linspace(0, 1, GS), GS), y=np.tile(np.linspace(0, 1, GS), GS)
)
.update_traces(marker_color="rgba(0,0,0,0)")
.data
)
# Build App
app = JupyterDash(__name__)
app.layout = dash.html.Div(
[dash.dcc.Graph(id="graph", figure=fig), dash.html.Div(id="where")]
)
#app.callback(
Output("where", "children"),
Input("graph", "clickData"),
)
def click(clickData):
if not clickData:
raise dash.exceptions.PreventUpdate
return json.dumps({k: clickData["points"][0][k] for k in ["x", "y"]})
# Run app and display result inline in the notebook
app.run_server(mode="inline")

Plotly combined barplot and table controled by range slider

I'm currently trying to create a graph with plotly,
My goal would be to create a combined Barplot / Data table both controled with a range slider in order to controle the values with the date. I've succeded to create the barplot controled with the range slider.
I can't manage to control the table :/
Here is a combined plot but where the range slider is attached to the table, as you can see it does not control the date but the table view
https://plotly.com/~tristan1551/31/
Here is an exemple of a barplot i've done with a range slider https://plotly.com/~tristan1551/23/
Another idea would be to only to control the table with the ranger slider, i can't manager to do that too.
Is there a way to achive what i want to do ?
Thank you for your herlp :)
to synchronise a table with a range slider on a figure you can use a dash callback
below code creates a bar chart with a rangeslider
attaches a callback to changes in figure to get position of rangeslider
constructs table based on these inputs
from jupyter_dash import JupyterDash
import dash_core_components as dcc
import dash_html_components as html
import dash_table
from dash.dependencies import Input, Output, State
import pandas as pd
import numpy as np
import plotly.express as px
df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/2014_apple_stock.csv")
df["AAPL_x"] = pd.to_datetime(df["AAPL_x"])
fig = px.bar(df, x="AAPL_x", y="AAPL_y").update_layout(
xaxis={
"range": [df["AAPL_x"].quantile(0.9), df["AAPL_x"].max()],
"rangeslider": {"visible": True},
}
)
# Build App
app = JupyterDash(__name__)
app.layout = html.Div(
[dcc.Graph(id="bargraph", figure=fig), html.Div(id="bartable", children=[])],
)
#app.callback(
Output("bartable", "children"),
Input("bargraph", "relayoutData"),
)
def updateTable(graphData):
global df
if graphData and "xaxis.range" in graphData.keys():
d1 = pd.to_datetime(graphData["xaxis.range"][0])
d2 = pd.to_datetime(graphData["xaxis.range"][1])
else:
d1 = df["AAPL_x"].quantile(0.9)
d2 = df["AAPL_x"].max()
dft = df.loc[df["AAPL_x"].between(d1, d2)]
return dash_table.DataTable(
columns=[{"name": c, "id": c} for c in dft.columns],
data=dft.to_dict("records"),
)
# Run app and display result inline in the notebook
app.run_server(mode="inline")

Dash/plotly, show only top 10 values in histogram

I am creating a dashboard in dash for a course at university. I created 3 histograms however, there are many unique values which give a long range of x values. In my plots I would like to show only the 10 or 20 values that have the highest count (top 10 values). Can someone help me out?
import plotly.express as px
from jupyter_dash import JupyterDash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
# Build App
app = JupyterDash(__name__)
app.layout = html.Div([
html.H1("forensics "),
dcc.Graph(id='graph'),
dcc.Graph(id='graph1'),
dcc.Graph(id='graph2'),
html.Label([
"select market",
dcc.Dropdown(
id='market', clearable=False,
value='whitehousemarket', options=[
{'label': c, 'value': c}
for c in posts['marketextract'].unique()
])
]),
])
# Define callback to update graph
#app.callback(
Output('graph', 'figure'),
Output('graph1', 'figure'),
Output('graph2', 'figure'),
[Input("market", "value")]
)
def update_figure(market):
fig=px.histogram(x=posts['datetime'].loc[posts['marketextract']==market])
fig1=px.histogram(x=posts['username'].loc[posts['marketextract']==market])
fig2=px.histogram(x=posts['drugs'].loc[posts['marketextract']==market])
return [fig, fig1, fig2]
# Run app and display result inline in the notebook
app.run_server(mode='inline')
To my knowledge, px.histogram() does not have a method to exclude certain observations of bins. But judging by the look of your data (please consider sharing a proper sample), what you're doing here is just showing the different counts of some user names. And you can easily do that through a combination of df.groupby() and px.histogram. Or px.bar() or go.Bar() for that matter, but we'll stick with px.histogram since that is what you're seeking help with. Anyway, using random selections of country names from px.gapminder you can use:
dfg = df.groupby(['name']).size().to_frame().sort_values([0], ascending = False).head(10).reset_index()
fig = px.histogram(dfg, x='name', y = 'count')
And get:
If you drop .head(10) you'll get this instead:
And I hope this is the sort of functionality you were looking for. And don't be intimidated by the long df.groupby(['name']).size().to_frame().sort_values([0], ascending = False).reset_index(). I'm not a pandas expert, so you could quite possibly find a more efficient approach. But it does the job. Here's the complete code with some sample data:
# imports
import pandas as pd
import plotly.express as px
import random
# data sample
gapminder = list(set(px.data.gapminder()['country']))[1:20]
names = random.choices(gapminder, k=100)
# data munging
df = pd.DataFrame({'name':names})
dfg = df.groupby(['name']).size().to_frame().sort_values([0], ascending = False).reset_index()
dfg.columns = ['name', 'count']
# plotly
fig = px.histogram(dfg, x='name', y = 'count')
fig.layout.yaxis.title.text = 'count'
fig.show()

How to create a vertical scroll bar with Plotly?

I would like to create a vertical scroll for a line chart in Plotly. For visualisation, the vertical scroll is something depicted in the figure below.
Assume, we have 6 line chart as below, then how can we create a vertical scroll bar on the canvas
import plotly.graph_objects as go
import plotly.io as pio
from plotly.subplots import make_subplots
import pandas as pd
# data
pio.templates.default = "plotly_white"
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv')
df = df.set_index('Date')
df.tail()
cols = df.columns[:-4]
ncols = len(cols)
# subplot setup
fig = make_subplots(rows=ncols, cols=1, shared_xaxes=True)
for i, col in enumerate(cols, start=1):
fig.add_trace(go.Scatter(x=df[col].index, y=df[col].values), row=i, col=1)
fig.show()
Thanks for any tips or good reading material.
I made a single page web app using plotly-dash. In this dashboard I wanted to create a vertical bar chart that also had a sroller on the side.
I imported the following dependencies:
from dash.dependencies import Input, Output, State
import dash_html_components as html
import dash_core_components as dcc
import dash_bootstrap_components as dbc
import dash
import dash_table
import plotly.graph_objs as go
import pandas as pd
In the app.layout I gave the css style parameters in the html.Div that contained my dcc.graph component:-
dcc.Graph(
id='doctors',
figure={}
),style={"maxHeight": "400px", "overflow": "scroll"})
], width={'size': 6})
Later in the #app callback I gave height to my vertical bar graph:-
fig.update_layout(height = (30*len(all_by_doctor)), title_text='Total bookings
by {} doctors'.format(len(all_by_doctor)),plot_bgcolor='#ffffff')

Showing a simple matplotlib plot in plotly Dash

Is it possible to show a simple matplotlib plot (the kind usually generated by plt.show()) in plotly's Dash framework? Or just plotly-like graphs with plotly's Scatters and Data traces?
Specifically I guess I need a different component than Graph (see below) and a way to return the simple plot in the update_figure function.
Example:
import dash
import dash_core_components as dcc
import dash_html_components as html
import numpy as np
import matplotlib.pyplot as plt
app = dash.Dash()
app.layout = html.Div(children=[
html.H1(children='Hello Dash'),
dcc.Slider(
id='n_points',
min=10,
max=100,
step=1,
value=50,
),
dcc.Graph(id='example') # or something other than Graph?...
])
#app.callback(
dash.dependencies.Output('example', 'figure'),
[dash.dependencies.Input('n_points', 'value')]
)
def update_figure(n_points):
#create some matplotlib graph
x = np.random.rand(n_points)
y = np.random.rand(n_points)
plt.scatter(x, y)
# plt.show()
return None # return what, I don't know exactly, `plt`?
if __name__ == '__main__':
app.run_server(debug=True)
Refer to https://plot.ly/matplotlib/modifying-a-matplotlib-figure/ . There is a mpl_to_plotly function in plotly.tools library that will return a plotly figure(which can then be returned to Graph's figure attribute) from matplotlib figure.
Edit: Just noticed you asked this a while back. Maybe the above is a new feature but its the cleanest way.
If you don't want an interactive plot, you can return a static one (found from this help)
import io
import base64
...
app.layout = html.Div(children=[
...,
html.Img(id='example') # img element
])
#app.callback(
dash.dependencies.Output('example', 'src'), # src attribute
[dash.dependencies.Input('n_points', 'value')]
)
def update_figure(n_points):
#create some matplotlib graph
x = np.random.rand(n_points)
y = np.random.rand(n_points)
buf = io.BytesIO() # in-memory files
plt.scatter(x, y)
plt.savefig(buf, format = "png")
plt.close()
data = base64.b64encode(buf.getbuffer()).decode("utf8") # encode to html elements
buf.close()
return "data:image/png;base64,{}".format(data)
UserWarning: Starting a Matplotlib GUI outside of the main thread will likely fail
in my case it works, despite the warning message 👍👍

Categories

Resources