Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Plotly animated slider in Python

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
like image 327
Caleb Everett Avatar asked Jul 23 '17 15:07

Caleb Everett


4 Answers

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!

  1. Plotly Animated Bubble Chart No Data in the Plot
  2. Plotly Error Invalid Figure or Data Argument
  3. Plotly Icreate Animations Offline on Jupyter Notebook
like image 139
Naren Murali Avatar answered Oct 27 '22 19:10

Naren Murali


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.

like image 23
0xc0de Avatar answered Oct 27 '22 21:10

0xc0de


You need plotly >= 2.0.0 try pip install plotly --upgrade

like image 37
user2147028 Avatar answered Oct 27 '22 19:10

user2147028


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

like image 28
user14492 Avatar answered Oct 27 '22 19:10

user14492