Plotly animated bubble chart: no data in the plot

被刻印的时光 ゝ 提交于 2019-12-04 06:16:16

问题


I am trying to adapt the standard plotly animated bubble chart to a csv file with these columns:

index,country,year,Country code,Total population (Gapminder),Life satisfaction in Cantril Ladder (World Happiness Report 2017),GDP per capita
62,Afghanistan,2008,AFG,29839994.0,3.723589897,1298.14315888
63,Afghanistan,2009,AFG,30577756.0,4.401778221,1531.17399272
64,Afghanistan,2010,AFG,31411743.0,4.75838089,1614.25500126
65,Afghanistan,2011,AFG,32358260.0,3.83171916,1660.73985618
66,Afghanistan,2012,AFG,33397058.0,3.782937527,1839.27357928
67,Afghanistan,2013,AFG,34499915.0,3.572100401,1814.15582533
167,Albania,2007,ALB,3169665.0,4.634251595,8447.88228539
169,Albania,2009,ALB,3192723.0,5.485469818,9524.60981095
170,Albania,2010,ALB,3204284.0,5.268936634,9927.13514733
171,Albania,2011,ALB,3215988.0,5.867421627,10207.7006745
172,Albania,2012,ALB,3227373.0,5.510124207,10369.7616592
173,Albania,2013,ALB,3238316.0,4.550647736,10504.0930888
242,Algeria,2010,DZA,35468208.0,5.46356678,12870.2162376
243,Algeria,2011,DZA,35980193.0,5.317194462,12989.9549601
244,Algeria,2012,DZA,36485828.0,5.604595661,13161.566464
451,Angola,2011,AGO,19618432.0,5.589000702,5911.25433387
452,Angola,2012,AGO,20162517.0,4.360249996,5998.63860099
453,Angola,2013,AGO,20714494.0,3.937106848,6185.0138292

The size of the datapoints will be a function of the population, and I'll plot life satisfaction as a function of the country's gdp. I work a bit on the dataset:

gdp=pd.read_csv('gdp-vs-happiness.csv')

gdp=gdp.ix[~(gdp['year'] < 2005)]
gdp=gdp.dropna()

dataset = gdp

and then here is the code:

years = ['2005','2006', '2007','2008','2009','2010','2011','2012','2013','2014','2015','2016']

# make list of continents
countries = []
for country in dataset['country']:
    countries.append(country)

# make figure
figure = {
    'data': [],
    'layout': {},
    'frames': []
}
config = {'scrollzoom': True}

# fill in most of layout
figure['layout']['xaxis'] = {'title': 'GDP per Capita', 'type': 'log'}
figure['layout']['yaxis'] = {'range': [0, 10], 'title': 'Life Satisfaction'}
figure['layout']['hovermode'] = 'closest'
figure['layout']['sliders'] = {
    'args': [
        'slider.value', {
            'duration': 400,
            'ease': 'cubic-in-out'
        }
    ],
    'initialValue': '2005',
    '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': []
}

# make data
year = 2005
for country in countries:
    dataset_by_year = dataset[dataset['year'] == year]
    dataset_by_year_and_count = dataset_by_year[dataset_by_year['country'] == country]
    data_dict = {
        'x': list(dataset_by_year_and_count['GDP per capita']),
        'y': list(dataset_by_year_and_count['Life satisfaction in Cantril Ladder (World Happiness Report 2017)']),
        'mode': 'markers',
        'text': list(dataset_by_year_and_count['country']),
        'marker': {
            'sizemode': 'area',
            'sizeref': 200000,
            'size': list(dataset_by_year_and_count['Total population (Gapminder)'])
        },
        'name': country

    }
    figure['data'].append(data_dict)

# make frames
for year in years:
    frame = {'data': [], 'name': str(year)}
    for country in countries:
        dataset_by_year = dataset[dataset['year'] == int(year)]
        dataset_by_year_and_cont = dataset_by_year[dataset_by_year['country'] == country]

        data_dict = {
        'x': list(dataset_by_year_and_count['GDP per capita']),
        'y': list(dataset_by_year_and_count['Life satisfaction in Cantril Ladder (World Happiness Report 2017)']),
            'mode': 'markers',
            'text': list(dataset_by_year_and_count['country']),
            'marker': {
                'sizemode': 'area',
                'sizeref': 200000,
                'size': list(dataset_by_year_and_count['Total population (Gapminder)'])
            },
        'name': country

        }
        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]

iplot(figure, config=config)

The issue here is that I get an empty plot (slider, layout, axis labels animation are working) with no data at all, and no error is raised. So I honestly don't know where the problem is. It obviously has something to do with the data building in the script but I don't know what precisely.


回答1:


I used the sample data you gave and worked on it, i've encounted few issues and added my comments on each line, the main reasons were pointed out in the comments section, but you can cross check my code with yours and get what you need

Code:

from plotly.offline import init_notebook_mode, iplot
from IPython.display import display, HTML

import pandas as pd

init_notebook_mode(connected=True)

url = 'testing.csv'
dataset = pd.read_csv(url)
# instead of hardcoding you can use unique() function to get the years present in the file, then convert to list and sort based on years
# years = dataset['year'].unique().tolist()
# years.sort()
years = ['2007','2008','2009','2010','2011','2012','2013'] # try to provide years that contain data in the data set

# make list of continents
countries = []
for country in dataset['country'].unique():
    countries.append(country)
# make figure
figure = {
    'data': [],
    'layout': {},
    'frames': []
}
config = {'scrollzoom': True}

# fill in most of layout

# there is a small ranging issue, where some points go out of the plot so try this code if you notice it

#figure['layout']['xaxis'] = {'title': 'GDP per Capita',  'autorange': False, 'range': [int(dataset['GDP per capita'].min()), int(dataset['GDP per capita'].max())]} #was not set properly
#figure['layout']['yaxis'] = {'title': 'Life Expectancy', 'autorange': False, 
#                             'range': [int(dataset['Life satisfaction in Cantril Ladder (World Happiness Report 2017)'].min()), 
#                                    int(dataset['Life satisfaction in Cantril Ladder (World Happiness Report 2017)'].max())]} #was not set properly


figure['layout']['xaxis'] = {'title': 'GDP per Capita', 'type': 'log', 'autorange': True} #was not set properly
figure['layout']['yaxis'] = {'title': 'Life Expectancy', 'autorange': True} #was not set properly
figure['layout']['hovermode'] = 'closest'
figure['layout']['showlegend'] = True
figure['layout']['sliders'] = {
    'args': [
        'slider.value', {
            'duration': 400,
            'ease': 'cubic-in-out'
        }
    ],
    'initialValue': '2007',
    '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': []
}

# make data -  here you need to specify the year being used as starting point, important to change
year = 2007
for country in countries:
    dataset_by_year = dataset[dataset['year'] == year]
    dataset_by_year_and_cont=dataset_by_year[dataset_by_year['country'] == country]

    data_dict = {
        'x': list(dataset_by_year_and_cont['GDP per capita']),
        'y': list(dataset_by_year_and_cont['Life satisfaction in Cantril Ladder (World Happiness Report 2017)']),
        'mode': 'markers',
        'text': [country], # since there is only one country we do not need to provide the list for text -  
        #Suggestion: No need to have this
        'marker': {
            'sizemode': 'area',
            'sizeref': 200000,
            'size': list(dataset_by_year_and_cont['Total population (Gapminder)'])
        },
        'name': country
    }
    figure['data'].append(data_dict)

# make frames
for year in years:
    frame = {'data': [], 'name': str(year)}
    dataset_by_year = dataset[dataset['year'] == int(year)] # here this has been moved because if the country 
    # is not present for that particular year there is no need to plot those traces
    for country in dataset_by_year['country']:

        dataset_by_year_and_cont=dataset_by_year[dataset_by_year['country'] == country]

        data_dict = {
            'x': list(dataset_by_year_and_cont['GDP per capita']),
            'y': list(dataset_by_year_and_cont['Life satisfaction in Cantril Ladder (World Happiness Report 2017)']),
            'mode': 'markers',
            'text': [country], # since there is only one country we do not need to provide the list for text - 
            #Suggestion: No need to have this
            'marker': {
                'sizemode': 'area',
                'sizeref': 200000,
                'size': list(dataset_by_year_and_cont['Total population (Gapminder)'])
            },
            'name': country,
            'type': 'scatter',
            'showlegend': True
        }
        frame['data'].append(data_dict)

    figure['frames'].append(frame) #this block was indented and should not have been.
    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]

iplot(figure, config=config)

Output:



来源:https://stackoverflow.com/questions/45711830/plotly-animated-bubble-chart-no-data-in-the-plot

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!