My function to create figures looks as follows:
def bar_plot_plotly(self, frame=None):
md = self.get_book()
plotly.offline.init_notebook_mode(connected=True)
fig = go.Figure()
if md:
for step in range(2):
fig.add_trace(go.Indicator(
mode = "number+gauge+delta", value = md.qasks[step],
delta = {'reference': md.qasks[step]},
domain = {'x': [0, 0.4], 'y': [0.2*step, 0.2*step+0.1]},
title = {'text': str(md.asks[step])},
gauge = {
'shape': "bullet",
'axis': {'range': [min(md.qasks), max(md.qasks)]},
'threshold': {
'line': {'color': "red", 'width': 2},
'thickness': 0.75,
'value': md.qasks[step]},
'bar': {'color': "red"}}))
fig.add_trace(go.Indicator(
mode = "number+gauge+delta", value = md.qbids[step],
delta = {'reference': md.qbids[step]},
domain = {'x': [0.6, 1], 'y': [0.2*step, 0.2*step+0.1]},
title = {'text': str(md.bids[step])},
gauge = {
'shape': "bullet",
'axis': {'range': [min(md.qbids), max(md.qbids)]},
'threshold': {
'line': {'color': "green", 'width': 2},
'thickness': 0.75,
'value': md.qbids[step]},
'bar': {'color': "green"}}))
So at each iteration, it creates a figure, my goal would be to iterate on each of those figures in order to create an animation. The idea would be to do the same as in the documentation https://plot.ly/python/animations/#animated-bar-charts-with-plotly-express, but in there they use a pandas DataFrame, I would like to do it per figure basically.
I used to use Funcanimation on matplotlib, I was thus wondering if it was possible to use the above code to do the same? Any advice is more than welcome!
Thanks
Related
I have a plotly dashboard built with dash. Some of the chart elements are set to refresh every couple of seconds. Instead of just refreshing that individual dashboard, the entire webpage refreshes and it rebuilds every element.
This is an example of how the code is written that updates the charts-
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div(
html.Div([
dcc.Graph(id='live-update-graph'),
dcc.Interval(
id='interval-component',
interval=1*1000, # in milliseconds
n_intervals=0
)
])
)
#app.callback(Output('live-update-graph', 'figure'),
Input('interval-component', 'n_intervals'))
def update_graph_live(n):
satellite = Orbital('TERRA')
data = {
'time': [],
'Latitude': [],
'Longitude': [],
'Altitude': []
}
# Collect some data
for i in range(180):
time = datetime.datetime.now() - datetime.timedelta(seconds=i*20)
lon, lat, alt = satellite.get_lonlatalt(
time
)
data['Longitude'].append(lon)
data['Latitude'].append(lat)
data['Altitude'].append(alt)
data['time'].append(time)
# Create the graph with subplots
fig = plotly.tools.make_subplots(rows=2, cols=1, vertical_spacing=0.2)
fig['layout']['margin'] = {
'l': 30, 'r': 10, 'b': 30, 't': 10
}
fig['layout']['legend'] = {'x': 0, 'y': 1, 'xanchor': 'left'}
fig.append_trace({
'x': data['time'],
'y': data['Altitude'],
'name': 'Altitude',
'mode': 'lines+markers',
'type': 'scatter'
}, 1, 1)
return fig
My desired outcome is that just the plot element refreshes but not the entire webpage.
I would like to display multi bullet charts and icons using dash and plotly in separate rows. I would like them to display something like the image below. I've already implemented the multi bullet chart on one row. I'm having trouble placing another multi bullet chart beside this one with icons because of the domain x and y positioning. Here's the code that I have so far. Once I get this I would be adding a drop down to display this information.
app = dash.Dash(__name__)
fig = go.Figure()
fig.add_trace(go.Indicator(
mode = "number+gauge+delta", value = 180,
delta = {'reference': 200},
domain = {'x': [0.25, 1], 'y': [0.08, 0.25]},
title = {'text': "SV 3"},
gauge = {'shape': "bullet"}))
fig.add_trace(go.Indicator(
mode = "number+gauge+delta", value = 35,
delta = {'reference': 200},
domain = {'x': [0.25, 1], 'y': [0.4, 0.6]},
title = {'text': "SV 2"},
gauge = {'shape': "bullet"}))
fig.add_trace(go.Indicator(
mode = "number+gauge+delta", value = 220,
delta = {'reference': 200},
domain = {'x': [0.25, 1], 'y': [0.7, 0.9]},
title = {'text' :"SV 1"},
gauge= {'shape': "bullet"}))
fig.update_layout(height = 400 , margin = {'t':0, 'b':0, 'l':0})
fig.show()
app.run_server(debug=True, use_reloader=True)
I would recommend you to work with dash-bootstrap-components!
layout = html.Div(
[
dbc.Row(
dbc.Col
(html.Div("A single, half-width column"), width=6)),
dbc.Row(
[
dbc.Col(fig, width=3),
dbc.Col(html.Div("Some space in the middle")),
dbc.Col(html.Div("One of your other elements"), width=3),
]
),
]
)
I'm using Plotly gauge charts in my Django project. I need to show two thresholds for the upper and lower boundary of some parameter which is being projected in the chart.
here is my chart in views.py:
gauge_do = go.Figure(go.Indicator(
mode = "gauge+number",
value = 1.7,
domain = {'x': [0, 1], 'y': [0, 1]},
title = {'text': "Oxygen [mg/L]"},
gauge = {'axis': {'range': [0, 10]},
'bar': {'color': "salmon"},
'threshold' : {'line': {'color': "red", 'width': 4}, 'thickness': 0.75, 'value': 2}
}
)
)
gauge_do.update_layout(font = {'color': "black", 'family': "Arial"}, margin = dict(t=0, b=0, l=5, r=5,), height=230)
div_do = opy.plot(gauge_do, auto_open=False, config=config, output_type='div')
Here, there is one threshold with value of 'value': 2.
In my case, I want to show the minimum acceptable value and maximum acceptable value by two indicators ( exactly as threshold ), say min=2 and max=8.
the plotly doesnt accept using two 'threshold's.
any ideas?
From the documentation, it seems like they intend steps to do this. Something like:
gauge_do = go.Figure(
go.Indicator(
mode = "gauge+number",
value = 1.7,
domain = {'x': [0, 1], 'y': [0, 1]},
title = {'text': "Oxygen [mg/L]"},
gauge = {'axis': {'range': [0, 10]},
'bar': {'color': "salmon"},
'steps' : [{
'color': 'white',
'line': {'color': "red", 'width': 4},
'thickness': 0.75,
'range': [2,8]}]
}
)
)
I was trying to recreate this example in a Jupyter notebook.
https://plot.ly/python/gapminder-example/
but was getting this error:
PlotlyDictKeyError: 'slider' is not allowed in 'layout'
Path To Error: ['layout']['slider']
Valid attributes for 'layout' at path ['layout'] under parents ['figure']:
['angularaxis', 'annotations', 'autosize', 'bargap', 'bargroupgap',
'barmode', 'barnorm', 'boxgap', 'boxgroupgap', 'boxmode', 'calendar',
'direction', 'dragmode', 'font', 'geo', 'height', 'hiddenlabels',
'hiddenlabelssrc', 'hidesources', 'hoverlabel', 'hovermode', 'images',
'legend', 'mapbox', 'margin', 'orientation', 'paper_bgcolor',
'plot_bgcolor', 'radialaxis', 'scene', 'separators', 'shapes',
'showlegend', 'sliders', 'smith', 'ternary', 'title', 'titlefont',
'updatemenus', 'width', 'xaxis', 'yaxis']
Run `<layout-object>.help('attribute')` on any of the above.
'<layout-object>' is the object at ['layout']
The animation runs without the slider dict added to layout and the slider is visible and operational, but does not change the graph. When I move the slider it produces the following error in the console:
Uncaught (in promise) undefined
Update:
I checked the graph you have, I am observing the below error sometimes.
Uncaught (in promise) undefined
This error might by due to plotly missing an click or other event, but this is internally within the plotly.js file, if you go to Plotly Slider animation link and to the slider animation section, click play and click on the slider while play is running we get this error, even when I click on pause I get this error. But the animation keeps on playing if I press the play again, hence there is no major impact! It's just that an event is not handled properly.
So as in the case of the graph you provided, I can get the animation working fine, eventhough I get the error (Uncaught (in promise) undefined) I am still able to play the animation!
You can use either iplot(fig, validate=False) or plot(fig) to show the graphs in Python with the animation!
Answer:
The error is because the layout object has a property called sliders not slider, so wherever you are using slider under layout, please change this, also this plot is very complicated and may have other errors also, please share the code, for debugging. But for now this will be my answer.
Before:
['layout']['slider']
After:
['layout']['sliders']
Please replace all the slider properties that are related to layout, these need to be changed to sliders.
References:
I have handled issues related to this particular slider animated Plotly graph. Please refer to them if need, they may help solve your issue!
Plotly Animated Bubble Chart No Data in the Plot
Plotly Error Invalid Figure or Data Argument
Plotly Icreate Animations Offline on Jupyter Notebook
You are probably hitting this error because of a typo in that notebook. It should be sliders instead of slider, see the docs.
The other error too, seems to be caused by this typo. It seems that this code is in an event handler that gets triggered whenever you move the slider.
So below line (and similar ones):
figure['layout']['slider']
should be corrected to:
figure['layout']['sliders']
Here is the code for that example:
import plotly.plotly as py
import plotly.graph_objs as go
from plotly.grid_objs import Grid, Column
from plotly.tools import FigureFactory as FF
import pandas as pd
import time
url = 'https://raw.githubusercontent.com/plotly/datasets/master/gapminderDataFiveYear.csv'
dataset = pd.read_csv(url)
table = FF.create_table(dataset.head(10))
py.iplot(table, filename='animations-gapminder-data-preview')
years_from_col = set(dataset['year'])
years_ints = sorted(list(years_from_col))
years = [str(year) for year in years_ints]
years.remove('1957')
# make list of continents
continents = []
for continent in dataset['continent']:
if continent not in continents:
continents.append(continent)
columns = []
# make grid
for year in years:
for continent in continents:
dataset_by_year = dataset[dataset['year'] == int(year)]
dataset_by_year_and_cont = dataset_by_year[dataset_by_year['continent'] == continent]
for col_name in dataset_by_year_and_cont:
# each column name is unique
column_name = '{year}_{continent}_{header}_gapminder_grid'.format(
year=year, continent=continent, header=col_name
)
a_column = Column(list(dataset_by_year_and_cont[col_name]), column_name)
columns.append(a_column)
# upload grid
grid = Grid(columns)
url = py.grid_ops.upload(grid, 'gapminder_grid'+str(time.time()), auto_open=False)
figure = {
'data': [],
'layout': {},
'frames': [],
'config': {'scrollzoom': True}
}
# fill in most of layout
figure['layout']['xaxis'] = {'range': [30, 85], 'title': 'Life Expectancy', 'gridcolor': '#FFFFFF'}
figure['layout']['yaxis'] = {'title': 'GDP per Capita', 'type': 'log', 'gridcolor': '#FFFFFF'}
figure['layout']['hovermode'] = 'closest'
figure['layout']['plot_bgcolor'] = 'rgb(223, 232, 243)'
figure['layout']['sliders'] = {
'args': [
'slider.value', {
'duration': 400,
'ease': 'cubic-in-out'
}
],
'initialValue': '1952',
'plotlycommand': 'animate',
'values': years,
'visible': True
}
figure['layout']['updatemenus'] = [
{
'buttons': [
{
'args': [None, {'frame': {'duration': 500, 'redraw': False},
'fromcurrent': True, 'transition': {'duration': 300, 'easing': 'quadratic-in-out'}}],
'label': 'Play',
'method': 'animate'
},
{
'args': [[None], {'frame': {'duration': 0, 'redraw': False}, 'mode': 'immediate',
'transition': {'duration': 0}}],
'label': 'Pause',
'method': 'animate'
}
],
'direction': 'left',
'pad': {'r': 10, 't': 87},
'showactive': False,
'type': 'buttons',
'x': 0.1,
'xanchor': 'right',
'y': 0,
'yanchor': 'top'
}
]
sliders_dict = {
'active': 0,
'yanchor': 'top',
'xanchor': 'left',
'currentvalue': {
'font': {'size': 20},
'prefix': 'Year:',
'visible': True,
'xanchor': 'right'
},
'transition': {'duration': 300, 'easing': 'cubic-in-out'},
'pad': {'b': 10, 't': 50},
'len': 0.9,
'x': 0.1,
'y': 0,
'steps': []
}
custom_colors = {
'Asia': 'rgb(171, 99, 250)',
'Europe': 'rgb(230, 99, 250)',
'Africa': 'rgb(99, 110, 250)',
'Americas': 'rgb(25, 211, 243)',
#'Oceania': 'rgb(9, 255, 255)'
'Oceania': 'rgb(50, 170, 255)'
}
col_name_template = '{year}_{continent}_{header}_gapminder_grid'
year = 1952
for continent in continents:
data_dict = {
'xsrc': grid.get_column_reference(col_name_template.format(
year=year, continent=continent, header='lifeExp'
)),
'ysrc': grid.get_column_reference(col_name_template.format(
year=year, continent=continent, header='gdpPercap'
)),
'mode': 'markers',
'textsrc': grid.get_column_reference(col_name_template.format(
year=year, continent=continent, header='country'
)),
'marker': {
'sizemode': 'area',
'sizeref': 200000,
'sizesrc': grid.get_column_reference(col_name_template.format(
year=year, continent=continent, header='pop'
)),
'color': custom_colors[continent]
},
'name': continent
}
figure['data'].append(data_dict)
for year in years:
frame = {'data': [], 'name': str(year)}
for continent in continents:
data_dict = {
'xsrc': grid.get_column_reference(col_name_template.format(
year=year, continent=continent, header='lifeExp'
)),
'ysrc': grid.get_column_reference(col_name_template.format(
year=year, continent=continent, header='gdpPercap'
)),
'mode': 'markers',
'textsrc': grid.get_column_reference(col_name_template.format(
year=year, continent=continent, header='country'
)),
'marker': {
'sizemode': 'area',
'sizeref': 200000,
'sizesrc': grid.get_column_reference(col_name_template.format(
year=year, continent=continent, header='pop'
)),
'color': custom_colors[continent]
},
'name': continent
}
frame['data'].append(data_dict)
figure['frames'].append(frame)
slider_step = {'args': [
[year],
{'frame': {'duration': 300, 'redraw': False},
'mode': 'immediate',
'transition': {'duration': 300}}
],
'label': year,
'method': 'animate'}
sliders_dict['steps'].append(slider_step)
figure['layout']['sliders'] = [sliders_dict]
py.icreate_animations(figure, 'gapminder_example'+str(time.time()))
Note: Strange but the code executed successfully for me with the above mentioned typo as well!
Demo output.
You need plotly >= 2.0.0
try
pip install plotly --upgrade
As others have mentioned, the documentation is incorrect. But simply replacing all slider with sliders will still give an error. Therefore, here's a self contained example.
http://nbviewer.jupyter.org/gist/empet/365cf202391bf7a58021388fadd52004
I am trying to add a hyperlink to a cell to open a folder the code below makes the hyperlink in the proper cell and is when clicked redirects to the proper folder but it does not display the text provided it instead displays the folder name e.g. (:C:\Documents and Settings\abulle\Desktop\Python-Stuff\Spec-Load\Formatted\) instead of 'Folder'
sheet.Hyperlinks.Add( Anchor = sheet.Cells(7,21), Address = "C:\\Python-Stuff\\Spec-Load\\Formatted\\" , TextToDisplay = "Folder")
I have a stopgap answer, a kludge. I don't have time at the moment to find a better answer. If this was part of my day job I'd spend the time to find out what's going on.
I've had the same issue (Excel shows the link address as the cell text instead of the TextToDisplay value supplied on Hyperlinks.Add())
My code works under unit test when invoked by running the Python 2.7 interpreter - the value of the 'TextToDisplay' argument is displayed in the cell. The 'production' code (built using py2exe) displays the hyperlink. I'll find out why some day (this is low background work.)
Hyperlinks.Add returns the Hyperlink object it just added. The workaround is to examine the TextToDisplay property of that object - if it's not what I want, I assign the correct value to it.
link = sheet.Hyperlinks.Add( Anchor = sheet.Cells(7,21),
Address = u"C:\\Python-Stuff\\Spec-Load\\Formatted\\" ,
TextToDisplay = u"Folder")
if link.TextToDisplay != u"Folder":
link.TextToDisplay = u"Folder" # kludge
try this
def addHyperlink(self, uri_1, summa_, sheetId, rowIndex, colIndex):
requests = []
requests.append({
"updateCells": {
"rows": [{
"values": [{
'userEnteredValue': {'numberValue': floatG(summa_)}, #
'effectiveValue': {'numberValue': floatG(summa_)},
'formattedValue': "р." + summa_,
'userEnteredFormat': {
'numberFormat': {'type': 'NUMBER', 'pattern': '[$р.-419]#,##0.00'},
'backgroundColor': {'red': 1, 'green': 1, 'blue': 0.6}, 'borders': {
'top': {
'style': 'SOLID', 'width': 1, 'color': {}, 'colorStyle': {'rgbColor': {}}},
'bottom': {
'style': 'SOLID', 'width': 1, 'color': {}, 'colorStyle': {'rgbColor': {}}},
'left': {
'style': 'SOLID', 'width': 1, 'color': {}, 'colorStyle': {'rgbColor': {}}},
'right': {
'style': 'SOLID', 'width': 1, 'color': {}, 'colorStyle': {'rgbColor': {}}}},
'horizontalAlignment': 'RIGHT', 'verticalAlignment': 'BOTTOM',
'textFormat': {
'foregroundColor': {'red': 0.06666667, 'green': 0.33333334, 'blue': 0.8},
'fontFamily': 'Arial', 'underline': True,
'foregroundColorStyle': {
'rgbColor': {'red': 0.06666667, 'green': 0.33333334, 'blue': 0.8}},
'link': {'uri': uri_1}
},
'hyperlinkDisplayType': 'LINKED',
'backgroundColorStyle': {'rgbColor': {'red': 1, 'green': 1, 'blue': 0.6}}
}
, 'hyperlink': uri_1, 'note': 'макс',
}
]
}], "fields": "userEnteredFormat(numberFormat,backgroundColor,horizontalAlignment,verticalAlignment,textFormat)", "start": {
"sheetId": sheetId, "rowIndex": rowIndex, "columnIndex": colIndex}}})
body = {
"requests": requests}
request = self.service.spreadsheets().batchUpdate(spreadsheetId=self.spreadsheetId, body=body)
return request.execute()