用 Python 动态曲线图来对全球疫情进行演示
作者:Lemon
出品:Python数据之道
用 Python 动态曲线图来对全球疫情进行演示
数据来源
准备工作
Mac 系统
Anaconda(Python 3.7)
Jupyter Notebook
# 从 akshare 获取数据
# df_all_history = ak.epidemic_history()
# 从csv文件获取数据,这个数据文件的数据截止到3月28日
df_all_history = pd.read_csv('epidemic_all_20200328.csv',index_col=0)
df_all_history
# 整理数据
# 将数据复制一份
df_all = df_all_history
# 将字符串格式的日期 另保存为一列
# df_all['dates'] = df_all_history['date']
# 将字符串格式的日期转换为 日期格式
df_all['date'] = pd.to_datetime(df_all['date'])
# 将时间格式转为字符串格式的日期,以 YYYY-mm-dd 的形式保存
df_all['dates'] = df_all['date'].apply(lambda x:x.strftime('%Y-%m-%d'))
# 添加现存确诊列
df_all['current'] = df_all['confirmed'] - df_all['cured'] - df_all['dead']
df_all.fillna('', inplace=True)
print(df_all.info())
df_all
获取国外和国内的疫情数据
# 国内总计数量
df_china_total = df_all.query("country=='中国' and province==''")
df_china_total = df_china_total.sort_values('date',ascending=False)
# df_china_total
# 国外,按国家统计
df_oversea = df_all.query("country!='中国'")
df_oversea.fillna(value="", inplace=True)
# df_oversea
df_oversea_total = df_oversea.groupby(['date','dates'])['confirmed','cured','dead','current'].sum()
df_oversea_total.reset_index(level=1,inplace=True)
df_oversea_total['district'] = 'oversea'
# df_oversea_total
df_china_sum = df_china_total[['date','dates','confirmed','cured','dead','current']]
df_china_sum.set_index('date',inplace=True)
df_china_sum['district'] = 'China'
# df_china_sum
df_total = df_oversea_total.append(df_china_sum)
df_total.sort_index(ascending=True,inplace=True)
df_total
# 国外从 1月16日起,才开始有统计数据
df_total_analysis = df_total['20200116':]
df_total_analysis
疫情可视化
fig_total = px.line(df_total_analysis, x='dates', y='confirmed', line_group='district',
color='district', color_discrete_sequence=px.colors.qualitative.D3,
hover_name='district',template='plotly_white',
width=500,height=600,
title=dict(text='Covid-19-trend',
font=dict(size=16,color='#0071c1'),
x=0.5)
)
fig_total.show()
这里仅仅是做简单的可视化,至于将中国和海外国家总体做对比分析,是否合理,这里只是个示例,不做进一步阐述。
px.line
中,Lemon 也研究了下,暂时没有实现将曲线进行动态可视化的功能。动态曲线演示疫情情况
对初始状态进行可视化,每条曲线将起始的两个点绘制成曲线;
通过构造字典的形式,在
frames
中实现曲线的动态变化;添加演示按钮,
# 日期
d = datetime.today().day
m = datetime.today().month
text_today = f'数据统计截止{m}月{d}日'
# 海外数据
df_oversea_analysis = df_total_analysis.query('district=="oversea"')
# 国内数据
df_cn_analysis = df_total_analysis.query('district=="China"')
# 计算 最大的确诊人数
y_max_cn = df_cn_analysis['confirmed'].max()
y_max_oversea = df_oversea_analysis['confirmed'].max()
y_max = max(y_max_cn,y_max_oversea)
# China
trace1 = go.Scatter(x=df_cn_analysis.index[:2],
y=df_cn_analysis['confirmed'][:2],
mode='lines',
name='China',
line=dict(width=1.5,
color='#FFD300'))
# oversea
trace2 = go.Scatter(x = df_oversea_analysis.index[:2],
y = df_oversea_analysis['confirmed'][:2],
mode='lines', # markers+lines
name='Oversea',
line=dict(width=1.5))
frames = [dict(data= [dict(type='scatter',
x=df_cn_analysis.index[:k+1],
y=df_cn_analysis['confirmed'][:k+1]),
dict(type='scatter',
x=df_oversea_analysis.index[:k+1],
y=df_oversea_analysis['confirmed'][:k+1])],
traces= [0, 1],
# 0: frames[k]['data'][0],代表 trace1, 1:frames[k]['data'][1], trace2
)for k in range(1, len(df_cn_analysis))]
layout = go.Layout(width=500,
height=600,
showlegend=True,
template='plotly_dark',
hovermode='closest',
updatemenus=[dict(type='buttons', showactive=False,
y=1.10,
x=1.15,
xanchor='right',
yanchor='top',
pad=dict(t=0, r=10),
buttons=[dict(label='Play',
method='animate',
args=[None,
dict(frame=dict(duration=100,
redraw=False),
transition=dict(duration=1),
fromcurrent=True,
mode='immediate')])])],
)
layout.update(xaxis =dict(range=[df_cn_analysis.index[0],
df_cn_analysis.index[len(df_cn_analysis)-1]+pd.Timedelta(days=2)
],
autorange=False),
yaxis =dict(range=[0, y_max*1.05], autorange=False))
fig = go.Figure(data=[trace1, trace2], frames=frames, layout=layout)
fig.show()
go.Layout
中的 duration
可以来控制按钮点击后变化的速度。PS:如果曲线数量较少,你可以手动添加几条曲线,如果曲线数量较多,或者数量经常变化,则需要更加灵活的方式来实现。
-------------------End-------------------
扫描回复 “600”
获取《Python知识手册》