背景:本人是一名互联网从业人员(运营岗),从今年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
绘制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)
绘制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)
绘制湖北省随时间走势数据
#按时间删除重复项,即各省每日只保留一条最新的数据
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)
特殊问题
#由于中国整体的数据从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')]
#境外输入的数据会算到各个市里
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)