问题描述
我正在尝试将标准绘图动画气泡图调整为包含这些列的 csv 文件:
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
数据点的大小将是人口的函数,我会将生活满意度绘制为国家 GDP 的函数.我在数据集上做了一些工作:
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
然后是代码:
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.
推荐答案
我使用了您提供的示例数据并进行了处理,我遇到了一些问题并在每一行添加了我的评论,主要原因在评论部分,但你可以交叉检查我的代码和你的代码并得到你需要的东西
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
代码:
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)
输出:
这篇关于Plotly 动画气泡图:图中没有数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!