数据可视化:Python+Plotly绘制新冠疫情走势图(一)

背景:本人是一名互联网从业人员(运营岗),从今年2月份开始零基础自学Python,目前学习了两个月,主要对数据分析方面比较感兴趣,Python很多内容直接跳过了,所以基础不太扎实,3月集中在学Pandas和Plotly绘图,最近趁着假期,尝试利用所学知识结合新冠疫情进行数据分析,因个人水平有限,如有不足欢迎斧正!

数据源

我在网上搜索了很多相关数据,包括爬虫类的,因为还没掌握爬虫数据处理的相关知识,比较头疼,无意间在Github上查到这份csv格式的数据,非常方便用于数据分析。

新冠疫情数据(实时更新)

我采用的是:DXYArea.csv这份文件,其中包含中国境内省市级、港澳台地区及海外数据,数据更新至4月4日,目前还在不断更新中。

读取数据&基础处理

#导入基础模块
import pandas as pd
import numpy as np
from datetime import datetime
from pandas import to_datetime

#导入plotly
import plotly
import plotly.graph_objects as go
import plotly.offline as py  #设置离线画图

url = '/covid/DXYArea.csv'#此处将路径隐去
df = pd.read_csv(url,sep=',')#分隔符是逗号

df.info()

#通过对info的查看,发现updateTime类型是object,需要转换为datetime
df['updateTime'] = pd.to_datetime(df['updateTime'])
#新增一列用字符串格式表示的时间(年-月-日),可读性强,增加后会展示在表格的最后一列
df_dt=to_datetime(df.updateTime,format="%Y/%m/%d")
df_dt_str=df_dt.apply(lambda x: datetime.strftime(x,"%Y-%m-%d"))
df['时间'] = df_dt_str
updateTime类型为object.png

增加时间一列.png

绘制TOP15省份最新(4月4日)数据

处理数据

#观察数据,发现provinceName一列包含中国,代表中国整个国家的数据,而实际在取省份数据时需要剔除此项
df_province = df.loc[(df['countryName']=='中国')&(df['provinceName']!='中国')&(df['时间']=='2020-04-04')]
#countryName为中国,且provinceName不为中国,代表中国各省份数据

#观察数据,发现4月4日各省份数据有多条,是因为各省数据明细到市级维度,且province相关字段是省汇总数据,每个省下存在各个市的多条数据,需要删除省份重复数据
df_province['provinceName'].value_counts()
#以更新时间降序排列,保留首次出现的数据行,及更新时间最新的那一行的省份数据
df_province_latest=df_province.sort_values(by='updateTime',ascending=False).drop_duplicates(subset='provinceName',inplace=False)
#设置省份名称为索引
df_province_latest.set_index('provinceName',inplace=True)
#各省份按累计确诊人数倒序排列
df_province_latest.sort_values(by='province_confirmedCount',inplace=True,ascending=False)
各省份4月4日有多条数据

绘制TOP15省份最新数据图

#x轴是省份名称,取top15
name = df_province_latest.head(15).index
#累计确诊数
confirmedCount = df_province_latest.head(15)['province_confirmedCount']
#累计治愈数
curedCount = df_province_latest.head(15)['province_curedCount']
#疑似确诊数
suspectedCount = df_province_latest.head(15)['province_suspectedCount']
#条形图,左边y轴
trace1 = go.Bar(x = name, y = confirmedCount,name='累计确诊数',
               text = confirmedCount,textposition ='outside', textfont=dict(size=10))
trace2 = go.Bar(x = name, y = curedCount,name='累计治愈数',
               text = curedCount,textposition ='outside', textfont=dict(size=10))
#折线图,右边y轴
trace3 = go.Scatter(x = name,y = suspectedCount,mode='lines+text',name='疑似确诊数',
                                     xaxis='x', yaxis='y2',
                                   text = suspectedCount,
                                     textposition ='top center',
                                    textfont=dict(size=10,color='brown'),)
#trace合并
data1 = [trace1,trace2,trace3]
#设置图层信息
layout = go.Layout(yaxis2=dict(anchor='x', overlaying='y', side='right',title='疑似确诊数',),
                  title = dict(text = '确诊数TOP15省份数据',
                               xanchor = 'auto',),
                  xaxis = dict(title='省份',tickangle=-45,),
                  yaxis = dict(title='累计确诊数、累计治愈数'))
#画图
fig = go.Figure(data = data1,layout = layout)
py.iplot(fig)
确诊数TOP15省份数据

绘制湖北省随时间走势数据

#按时间删除重复项,即各省每日只保留一条最新的数据
df_hb = df.loc[df['provinceName']=='湖北省'].sort_values(by='updateTime',ascending=False).drop_duplicates(subset='时间',inplace=False)
#设置时间为索引
df_hb.set_index('时间',inplace=True)
#按时间升序排列,由远及近
df_hb.sort_values(by='时间',inplace=True)
#绘制湖北省各项数据随时间变化趋势图
date = df_hb.index
confirmedCount = df_hb['province_confirmedCount']
deadCount = df_hb['province_deadCount']
curedCount = df_hb['province_curedCount']
#取点生成trace
trace1 = go.Scatter(x = date,y = confirmedCount,mode='lines+text',name='累计确诊数',)
#死亡人数数据比较小,绘制在右侧Y轴
trace2 = go.Scatter(x = date,y = deadCount,mode='lines+text',name='死亡人数',
                     xaxis='x', yaxis='y2',)
data1 = [trace1,trace2]
#设置图层信息
layout = go.Layout(yaxis2=dict(anchor='x', overlaying='y', side='right',title='死亡人数',),
                  title = dict(text = '湖北省走势数据',
                               xanchor = 'auto',),
                  legend=dict(x=1.1,y=1),
                  xaxis = dict(title='时间',tickangle=-45,),
                  yaxis = dict(title='累计确诊数、'))
fig = go.Figure(data = data1,layout = layout)
#增加一张图:治愈数相关数据
fig.add_scatter(x = date,y = curedCount,mode='lines+text',name='治愈数',)
py.iplot(fig) 
湖北省走势数据

绘制武汉市走势数据

#区别是城市名称取cityname一列
df_wh = df.loc[df['cityName']=='武汉']
df_wh = df_wh.sort_values(by='updateTime',ascending=False).drop_duplicates(subset='时间',inplace=False)
df_wh.set_index('时间',inplace=True)
df_wh.sort_values(by='时间',inplace=True)
#增加死亡率和治愈率数据
df_wh['deathrate']=df_wh['city_deadCount']/df_wh['city_confirmedCount']
df_wh['curedrate']=df_wh['city_curedCount']/df_wh['city_confirmedCount']
#绘制武汉市各项数据随时间变化趋势图
date = df_wh.index
confirmedCount = df_wh['city_confirmedCount']
deadCount = df_wh['city_deadCount']
curedCount = df_wh['city_curedCount']
trace1 = go.Scatter(x = date,y = confirmedCount,mode='lines+text',name='累计确诊数',)
trace2 = go.Scatter(x = date,y = deadCount,mode='lines+text',name='死亡人数',
                     xaxis='x', yaxis='y2',)
data1 = [trace1,trace2]
layout = go.Layout(yaxis2=dict(anchor='x', overlaying='y', side='right',title='死亡人数',),
                  title = dict(text = '武汉市走势数据',
                               xanchor = 'auto',),
                  legend=dict(x=1.1,y=1),
                  xaxis = dict(title='时间',tickangle=-45,),
                  yaxis = dict(title='累计确诊数'),
                  width=1000,
                  height=800)
fig = go.Figure(data = data1,layout = layout)
fig.add_scatter(x = date,y = curedCount,mode='lines+text',name='治愈数',)
py.iplot(fig) 
武汉市走势数据

绘制武汉市死亡率和治愈率曲线图

#绘制武汉市死亡率和治愈率曲线图
date = df_wh.index
deathrate = df_wh['deathrate']
curedrate = df_wh['curedrate']
trace1 = go.Scatter(x = date,y = deathrate,mode='lines+text',name='死亡率', xaxis='x', yaxis='y2',
                   )
trace2 = go.Scatter(x = date,y = curedrate,mode='lines+text',name='治愈率',
                  )
data1 = [trace1,trace2]
layout = go.Layout(yaxis2=dict(anchor='x', overlaying='y', side='right',title='死亡率',),
                  title = dict(text = '武汉市死亡率-治愈率数据',
                               xanchor = 'auto',),
                  legend=dict(x=1.1,y=1),
                  xaxis = dict(title='时间',tickangle=-45,),
                  yaxis = dict(title='治愈率'))
fig = go.Figure(data = data1,layout = layout)
py.iplot(fig) 
武汉市死亡率-治愈率数据

绘制世界确诊人数前五的国家的数据图

#首先需要剔除中国各省市的数据,只保留国家整体的数据作为中国的数据
missing = df.loc[(df['provinceName']!='中国')&(df['countryName']=='中国')]#剔除provincename不是中国且countryname是中国的行,即所有省份的数据
df1 = df.drop(index=missing.index,inplace=False)#删除掉这些行,并把结果保存到df1中
df_notcnpro = df1.reset_index(drop=True)#重置df1的索引,结果赋值给df_notcnpro
#取出4月4日的数据,并按照国家-时间删除两项都重复的行(即一个国家对应4月4日多条数据的情况)
df_wd = df_notcnpro.loc[df_notcnpro['时间']=='2020-04-04'].sort_values(by='updateTime',ascending=False).drop_duplicates(subset=['countryName','时间'],inplace=False)
#将countryname设置为索引
df_wd.set_index('countryName',inplace=True)
#按照累计确诊人数降序排列
df_wd.sort_values(by='province_confirmedCount',ascending=False,inplace=True)
#绘制TOP5国家图表
name = df_wd.head(5).index
confirmedCount = df_wd.head(5)['province_confirmedCount']
curedCount = df_wd.head(5)['province_curedCount']
suspectedCount = df_wd.head(5)['province_suspectedCount'] 
deadCount = df_wd.head(5)['province_deadCount'] 
trace1 = go.Bar(x = name, y = confirmedCount,name='累计确诊数',
               text = confirmedCount,textposition ='outside', textfont=dict(size=10))
trace2 = go.Bar(x = name, y = curedCount,name='累计治愈数',
               text = curedCount,textposition ='outside', textfont=dict(size=10))
trace4 = go.Scatter(x = name,y = deadCount,mode='lines+text+markers',name='累计死亡数',
                                     xaxis='x', yaxis='y2',
                                   text = deadCount,
                                     textposition ='middle right',
                                    textfont=dict(size=10,color='brown'),)
data1 = [trace1,trace2,trace4]
layout = go.Layout(yaxis2=dict(anchor='x', overlaying='y', side='right',title='累计死亡数',),
                  title = dict(text = '确诊数TOP5国家数据',
                               xanchor = 'auto',),
                  xaxis = dict(title='国家',tickangle=-45,),
                  yaxis = dict(title='累计确诊数、累计治愈数'))
fig = go.Figure(data = data1,layout = layout)
py.iplot(fig) 
确诊数TOP5国家数据

特殊问题

#由于中国整体的数据从3.15开始才有,想试着通过groupby的方式把各个省的数据汇总求出中国每日的总数
#各省份数据删除每日重复的条数
df_cn = df.loc[(df['countryName']=='中国')&(df['provinceName']!='中国')].sort_values(by='updateTime',ascending=False).drop_duplicates(subset=['provinceName','时间'],inplace=False)
#按时间维度把每日各省份数据加和求出中国整体的数据
df_cn.groupby('时间').sum()
#4月4日中国最新数据是76984,跟上述方法(按省份加和)算出来的数据不一致,可能是统计口径的问题
df.loc[(df['provinceName']=='中国')&(df['时间']=='2020-04-04')]
按省份加和求出4.4累计是7.4w人

直接查询provincename为中国的数据,为7.6w人
#境外输入的数据会算到各个市里
df_cn.loc[(df_cn['provinceName']=='上海市')&(df['时间']=='2020-04-04')]
境外输入数据

统计各大洲数据

#逻辑参考绘制世界确诊TOP5国家时生成的df_wd
#首先需要剔除中国各省市的数据,只保留国家整体的数据
missing = df.loc[(df['provinceName']!='中国')&(df['countryName']=='中国')]#剔除provincename不是中国且countryname是中国的行,即所有省份的数据
df1 = df.drop(index=missing.index,inplace=False)#删除掉这些行,并把结果保存到df1中
df_notcnpro = df1.reset_index(drop=True)#重置df1的索引,结果赋值给df_notcnpro
#按照国家-时间删除两项都重复的行
df_wd = df_notcnpro.sort_values(by='updateTime',ascending=False).drop_duplicates(subset=['countryName','时间'],inplace=False)
#将countryname设置为索引
df_wd.set_index('countryName',inplace=True)
#按大洲和时间进行聚合
df_wd_sum = df_wd.groupby(['continentName','时间']).sum()
#由于中国作为国家整体的数据从3.15才有,因此3.15之前的数据可以采取按省份加和的数据,加入aisa的数据中
#df_0314表示1.29到3.14中国的数据
df_0314 = df_cn.groupby('时间').sum().loc['2020-01-29':'2020-03-14'].iloc[:,0:2]
#亚洲数据在3.14之前,加上中国的数据列
df_asia = df_wd_sum.loc['亚洲'].iloc[:,0:2].merge(df_0314.iloc[:,0:2],on='时间')
#按日期把中国的数据加入asia中,并将这列命名为“累计人数含中国”
df_asia['累计人数含中国']= df_asia['province_confirmedCount_x']+df_asia['province_confirmedCount_y']
#把3.15及以后的数据加到1.29到3.14的数据之后
df_asia_sum = df_asia['累计人数含中国'].append(df_wd_sum.loc['亚洲']['province_confirmedCount'].loc['2020-03-15':])
#绘制各大洲的走势图
data1 = []
#去掉其他洲
for i in df['continentName'].unique()[1:-2]:
    date = df_wd_sum.loc[i].index
    confirmedCount = df_wd_sum.loc[i]['province_confirmedCount']
    trace = go.Scatter(x = date ,y = confirmedCount,mode='lines+text+markers',name='{}累计确诊数'.format(i),
                                   ) 
    data1.append(trace)
layout = go.Layout(
              title = dict(text = '各大洲累计确诊数据',
                           xanchor = 'auto',),
              xaxis = dict(title='大洲',tickangle=-45,),
              yaxis = dict(title='累计确诊数'),
width=1000,
height=800)
fig = go.Figure(data = data1,layout = layout)
fig.add_scatter(x = df_asia_sum.index,y = df_asia_sum,mode='lines+text+markers',name='亚洲累计确诊数',)
py.iplot(fig) 
各大洲累计确诊数据
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容