API爬虫
数据库存储和读取
数据预处理
数据分析及可视化
# 1、海外数据爬取# 国家名字爬取url = u'https://view.inews.qq.com/g2/getOnsInfo?name=disease_foreign'
headers = {'User_Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/
70.0.3538.25 Safari/537.36 Core/1.70.3756.400 QQBrowser/
10.5.4039.400'} # 模拟浏览器表头,防止反爬
r = requests.get(url, timeout=5, headers=headers)
data = json.loads(r.text) # json文件可以直接读取data = json.loads(data['data'])# 遍历国家名字,得到每个国家的数据all_date = {}for i in data['foreignList']:
url = 'https://api.inews.qq.com/newsqa/v1/automation/foreign/
daily/list?country={}'.format(i['name']) # i['name']是国家名字
r = requests.get(url,headers=headers)
data = json.loads(r.text)
data = data['data']
all_date[i['name']] = data
# 从每个国家数据筛选:国家名,累计确诊,新增确诊,新增治愈
,新增死亡等5个字段,并存储成列表
new_data = []for i in all_date.keys():
cur_data = all_date[i]for j in cur_data:
data = {'country':i,'date':j['date'],'confirm_add':j['confirm_add'],
'confirm':j['confirm'],'heal':j['heal'],'dead':j['dead']}
new_data.append(data)# 转变成pandas格式,便于后续与国内数据拼接df1 = pd.DataFrame(new_data)print(df1.head())
2、 爬取国内数据 国内数据用同样的方法,只不过所需字段分布在两个词典中,分批获取再拼接
# 2、国内数据爬取url = u'https://view.inews.qq.com/g2/getOnsInfo?name=disease_other'r = requests.get(url,headers=headers)
data = json.loads(r.text)
data_data = json.loads(data['data'])# 国内累计确诊,日期,累计治愈、累计死亡 5个字段在一个字典里all_data = []for i in data_data['chinaDayList']:
new_data = {}
new_data['country'] = '中国'new_data['confirm'] = i['confirm']
new_data['date'] = i['date']
new_data['dead'] = i['dead']
new_data['heal'] = i['heal']
all_data.append(new_data)# 国内新增确诊、日期在另一个字典里daily_data = []for i in data_data['chinaDayAddList']:
new_data = {}
new_data['confirm_add'] = i['confirm']
new_data['date'] = i['date']
daily_data.append(new_data)# 国内数据根据日期进行拼接df2 = pd.DataFrame(all_data)
df3 = pd.DataFrame(daily_data)
df4 = pd.merge(df2,df3,on='date')print(df4)
3 、海内外数据拼接
# 3、国内外数据横向拼接df = pd.concat([df1,df4],axis=0)# 转换成词典格式,方便保存至mysqldf = df.to_dict(orient='records')print(df)
Mysql数据存储和读取 一、数据库介绍 电脑有装Mysql和Mongdb数据库,均是免费使用。前者对数据的存储规范性要更高一些,存储速度慢,但非常便于pandas读取和分析;后者相反,存储很随意,速度快,就是读取数据较麻烦,且用的语言不是SQL,因此采用了Mysql 这是很早之前存储的一次数据,可以看下长啥样 二、数据存储代码 pandas第三方包pymysql,可以连接Mysql。连接之后,要建立数据库、建立表、然后再将之前的数据存储进去。这里还牵涉sql查询语言,不过很基础,不懂的可以百度下,代码如下:
# 导入库import pymysql
connection = pymysql.connect(host='localhost', # 连接数据库user='root',password='cindy407', # 你安装mysql时设置的密码charset='utf8',cursorclass=pymysql.cursors.DictCursor)
create_db = 'Create database if not exists pachong;' # 建立数据库drop_table = 'drop table if exists pachong.disease;' # 删除表格,因为要每天更新的话,需要先删除再重建create_table =''' Create table pachong.disease
(
country varchar(50),
date varchar(20),
confirm_add varchar(20),
confirm varchar(20),
heal varchar(20),
dead varchar(20)
);
''' # 创建表格字段alter_table = 'alter table pachong.disease convert to character set utf8;' # 这一步很关键,虽然连接时设置了语言为utf-8,但实际上还是没有改过来insert_table = '''insert into pachong.disease(country, date, confirm_add, confirm, heal, dead)
values(%s,%s,%s,%s,%s,%s)''' # 插入数据语句try:with connection.cursor() as cursor:
cursor.execute(create_db) # 分步执行sql语句cursor.execute(drop_table)
cursor.execute(create_table)
cursor.execute(alter_table)for item in df:
cursor.execute(insert_table, (
item['country'], item['date'], item['confirm_add'], item['confirm'], item['heal'], item['dead']))
connection.commit() # 提交sql,使之生效finally:
connection.close() # 关闭链接
三、数据读取 数据读取有2种方式,一是直接用pandas的read_sql函数直接导出数据+字段名,二是通过fetch_all函数将sql查询的数据导出,再导出字段名,拼接后得到数据+字段名,前者简单
# 数据读取connection = pymysql.connect(host='localhost',user='root',db='pachong',password='cindy407',charset='utf8',cursorclass=pymysql.cursors.DictCursor)
sql = 'select * from pachong.disease'data = pd.read_sql(sql,con=connection)print(data)# 这种读取方式也可以# with connection.cursor() as cursor:
# sql = "select * from pachong.disease"
# cursor.execute(sql)
# # 打印查询结果# result = cursor.fetchall()
# print(result)
利用pandas进行数据预处理 一、数据预处理 数据预处理,就是将原始数据变成可以直接进行分析的规整数据,主要有:重复值、缺失值、异常值、索引、列名、格式调整、排序等,之前有三篇文章总结过: Pandas系列②——数据清洗(重复值/缺失值/异常值) Pandas系列③——数据规整(索引/列名/格式/排序) Pandas系列④——数据拼接和透视 二、处理过程 其中缺失值和异常值都没有,无需处理,只是放一下代码而已
# 1、删除重复项print(data.duplicated().value_counts())
data.drop_duplicates(keep='first',inplace=True)# 2、缺失值处理print(data.info())# 3、修改数据型格式data[['confirm','confirm_add','heal','dead']] = data[['confirm','confirm_add','heal','dead']].astype('int')# 4、异常值处理print(data.describe())# 5、修改日期格式data['date'] = data['date'].apply(lambda x: '2020-' + x.replace('.','-'))# 6、增加中国/海外的标识(后续要进行海内外对比)data['if_foreign'] = data['country']
data.loc[data['if_foreign']=='中国','if_foreign']='中国'data.loc[data['if_foreign']!='中国','if_foreign']='海外'print(data.head())
处理后数据如下: 利用pyecharts&matplotlib进行可视化 一、海内外最新数据概览 取最新的日期的累计确诊、累计治愈、治愈率、累计死亡和死亡率数据,分海内外,进行对比,代码如下:
#
# 1、汇总概况:累计确诊、累计治愈、治愈率、累计死亡、死亡率# t = data.date.max() # 由于中国的数据更新要慢于海外1天,因此取前2天的分析t = '2020-05-09'a1 = data.loc[data['date'] == t]['confirm'].sum()
b1 = data.loc[data['date'] == t]['heal'].sum()
c1= data.loc[data['date'] == t]['heal'].sum()/data.loc[data['date'] == t]
['confirm'].sum()
d1 = data.loc[data['date'] == t]['dead'].sum()
e1 = data.loc[data['date'] == t]['dead'].sum()/data.loc[data['date'] == t]
['confirm'].sum()
a2 = data.loc[(data['date'] == t) & (data['country'] == '中国')]['confirm'].sum()
b2 = data.loc[(data['date'] == t) & (data['country'] == '中国')]['heal'].sum()
c2 = data.loc[(data['date'] == t) & (data['country'] == '中国')]['heal'].sum()/
data.loc[(data['date'] == t) & (data['country'] == '中国')]['confirm'].sum()
d2 = data.loc[(data['date'] == t) & (data['country'] == '中国')]['dead'].sum()
e2 = data.loc[(data['date'] == t) & (data['country'] == '中国')]['dead'].sum()/
data.loc[(data['date'] == t) & (data['country'] == '中国')]['confirm'].sum()
a3 = data.loc[(data['date'] == t) & (data['country'] != '中国')]['confirm'].sum()
b3 = data.loc[(data['date'] == t) & (data['country'] != '中国')]['heal'].sum()
c3 = data.loc[(data['date'] == t) & (data['country'] != '中国')]['heal'].sum()/
data.loc[(data['date'] == t) & (data['country'] != '中国')]['confirm'].sum()
d3 = data.loc[(data['date'] == t) & (data['country'] != '中国')]['dead'].sum()
e3 = data.loc[(data['date'] == t) & (data['country'] != '中国')]['dead'].sum()/
data.loc[(data['date'] == t) & (data['country'] != '中国')]['confirm'].sum()
# pandas行和列全部展示pd.options.display.max_rows=Nonepd.options.display.max_columns=None
print('全球:累计确诊 {:,}人,累计治愈 {:,}人,治愈率 {:0.2%},累计死亡 {:,}人,
死亡率 {:0.2%}'.format(a1,b1,c1,d1,e1))
print('中国:累计确诊 {:,}人,累计治愈 {:,}人,治愈率 {:0.2%},累计死亡 {:,}人,
死亡率 {:0.2%}'.format(a2,b2,c2,d2,e2))
print('海外:累计确诊 {:,}人,累计治愈 {:,}人,治愈率 {:0.2%},累计死亡 {:,}人,
死亡率 {:0.2%}'.format(a3,b3,c3,d3,e3))
结果如下,可以看出海外的死亡率高于中国1.3pct,说明中国的医疗水平以及治疗成果还是较好的 二、全球疫情分布 模仿今日头条,做一张全球分布地图,使用pyecharts的map做图,难点有二: 一是于海外国家,map只能读取英文名,不能读取中文,所以在网上找到了海外国家的中英文对应关系; 二是pyecharts去年更新了一版,与前一个版本不兼容,差距很大,而网上的教程多半是老版本的,所以倒腾了很久~~ 代码如下:
# 2、全球分布情况# map国外名称只能读取英文,所以要换成对应的英文名country_name = pd.read_csv('country_name.csv',header=None,names=['country_en','country'])
data = pd.merge(data,country_name,on = 'country',how='left')# 整理数据源x = list(data.loc[data['date'] ==t]['country_en'])
y = list(data.loc[data['date'] ==t]['confirm'])# 做图world = (
Map(init_opts=opts.InitOpts(theme=ThemeType.WESTEROS))
.add('世界地图',[list(z) for z in zip(x,y)],maptype="world",
is_map_symbol_show=False)
.set_series_opts(label_opts=opts.LabelOpts(is_show=False)) # 不显示国家名.set_global_opts(title_opts=opts.TitleOpts(title="nCoV全球疫情地图"),
visualmap_opts=opts.VisualMapOpts(is_piecewise=True,
pieces= # pieces可以设置不同区间颜色
[
{"min": 500001,"label":'50万以上',"color": '#800000'},{"min": 100001,"max":500000,"label":'10万-50万',"color": '#B22222'},{"min": 10001, "max": 100000, "label": '1万-10万', "color": "#FF8C00"}, # 不指定 max,表示 max 为无限大{"min": 5001, "max": 10000, "label": '5001-10000', "color": "#FA8072"},{"min": 501, "max": 5000, "label": '501-5000', "color": "#E9967A"},{"min": 101, "max": 500, "label": '101-500', "color": "#FFDEAD"},{"mim": 0, "max": 100, "label": '0-100', "color": "#FFF8DC"}
]))
)
world.render(r'C:\Users\cindy407\Desktop\世界地图.html')
# 导出HTML文件,可以在浏览器打开,也可渲染成图片
图片用浏览器打开如下,除了少数几个国家数据不全外,与今日头条还是非常红接近的 三、海内外各项指标的发展趋势及对比 这里重点对比了新增确诊、累计确诊、治愈率、死亡率四项指标的变化趋势,采用matplotlib库做图,代码如下:
#
# 3、海内外各项指标对比分析fig,axes = plt.subplots(2,2,figsize=(20,20))
plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置正常显示中文plt.rcParams['font.serif'] = ['SimHei'] # 设置正常显示中文# 新增确诊df1 = data.groupby(['date','if_foreign'])['confirm_add'].sum().unstack()
df1.index = pd.to_datetime(df1.index)
ax = plt.subplot(2,2,1)
ax.xaxis.set_major_formatter(mdate.DateFormatter('%Y-%m-%d'))
# 设置日期格式坐标,如果没有,会显示成数据格式
plt.xticks(pd.date_range(df1.index[0],df1.index[-1],freq='M'),size = 8)
# 设置日期展示间隔,freq M 是月,W 是周,Y是年等
plt.plot(df1.index,df1)
plt.legend(loc='best',labels=df1.columns)
plt.title('新增确诊人数')# 累计确诊df2 = data.groupby(['date','if_foreign'])['confirm'].sum().unstack()
df2.index = pd.to_datetime(df2.index)
ax = plt.subplot(2,2,2)
ax.xaxis.set_major_formatter(mdate.DateFormatter('%Y-%m-%d'))
plt.xticks(pd.date_range(df2.index[0],df2.index[-1],freq='M'),size = 8)
plt.plot(df2.index,df2)
plt.legend(loc='best',labels=df2.columns)
plt.title('累计确诊人数')# 治愈率
df3 = (data.groupby(['date','if_foreign'])['heal'].sum()/
data.groupby(['date','if_foreign'])['confirm'].sum()).unstack()
df3.index = pd.to_datetime(df3.index)
ax = plt.subplot(2,2,3)
ax.xaxis.set_major_formatter(mdate.DateFormatter('%Y-%m-%d'))
plt.xticks(pd.date_range(df3.index[0],df3.index[-1],freq='M'),size = 8)
plt.plot(df3.index,df3)
plt.legend(loc='best',labels=df3.columns)
plt.title('治愈率')# 死亡率
df4 = (data.groupby(['date','if_foreign'])['dead'].sum()/data.groupby
(['date','if_foreign'])['confirm'].sum()).unstack()
df4.index = pd.to_datetime(df4.index)
ax = plt.subplot(2,2,4)
ax.xaxis.set_major_formatter(mdate.DateFormatter('%Y-%m-%d'))
plt.xticks(pd.date_range(df4.index[0],df4.index[-1],freq='M'),size = 8)
plt.plot(df4.index,df4)
plt.legend(loc='best',labels=df4.columns)
plt.title('死亡率')
plt.show()
结果如下图: 1、海外新增处于反复波动的状态,且还未出现下降的趋势,疫情控制还遥遥无期;国内新增已经很少,只要严控境外输入,加强无症状人员治疗,没有太大问题 2、海外在新增无放缓的情况下,治愈率开始提升,目前是33%,有可能是医疗设施的提升,也有可能历史确诊病人已慢慢开始治愈;国内治愈率趋近94.5% 3、整体来看,死亡率在6.86%,海外死亡率近期开始下降,但仍比国内高1.3个百分点,国内在前一段时间修正了死亡人数,所以会出现陡增的情况 四、对比各国新增速度 对比各国新增的速度,以日期为维度是不行的,因为不同国家开始爆发的阶段不一样,所以以确诊人数同时达到某一个值时,以间隔天数作为维度来统计,能更好地对比,这个值我定的100,你也可以定别的。 只选了累计确诊超多5万的进行对比 + 可视化,代码如下:
# 4、全球累计>50000的国家的确诊趋势(限制人数从100开始)country = data[(data['date'] == t)&(data['confirm']>=50000)].sort_values('confirm', ascending=False)['country'].values
data = data[(data['country'].isin(country))&(data['confirm']>=100)]
fig,axes = plt.subplots(1,2,figsize=(20,40))
ax = plt.subplot(1,2,1)for i in country:
df1 = data[data.country==i]
plt.plot(list(range(1,len(df1)+1)),df1['confirm'])
plt.legend(loc='best',labels=country)# 踢掉美国,再看下:ax = plt.subplot(1,2,2)
country_sub = []for i in country:if i == '美国':continue
else:
df1 = data[data.country==i]
plt.plot(list(range(1,len(df1)+1)),df1['confirm'])
country_sub.append(i)
plt.legend(loc='best',labels=country_sub)
plt.show()
从结果来看,美国初期的新增速度与国内差不多,但在后期爆发式增长非常快,且没有一点抑制的状态,说明美国的防疫措施明显没有做到位 剔除掉美国后,可以看出中国在初期的新增速度是最快的,但在一个月内就基本控制住了疫情,对应于春假放假至正式复工这个阶段; 其余国家状态不一,有的已经开始接近拐点,比如西班牙、意大利、法国、德国、土耳其、伊朗、加拿大、比利时; 有的开始加快增长,比如俄罗斯、英国、巴西、秘鲁和印度。 比较担忧的是俄罗斯、巴西和印度,都是人口排名前10的国家,且目前都处于不断加快的阶段;其中印度医疗水平最低,人口又最多(13亿,仅次于中国14亿),由于检测能力有限,实际情况是不是要严重得多,也未能知。 五、前日新增TOP10国家
# 5、前日新增TOP10国家
df = data[data['date']==t].sort_values('confirm_add',ascending=False)[['country','confirm_add']].set_index('country',drop=True)
plt.bar(x=df.index.values[:10],height=df['confirm_add'].values[:10],width=0.5,color='b')
plt.title('昨日新增TOP10国家')
plt.show()
总结: 海外疫情十分严峻,且暂时还预测不了何时抵达拐点,国内目前虽然新增较少,但境外输入和无症状仍不可小憩,大家伙仍然要小心为上,出门还是戴上口罩吧。
end
福利: 1、关注公众号,回复' 病毒 '即可获得 本文全部代码和全球中英文对应文件 2、回复" 分析 "可以免费获得如下 9本数据分析经典书籍电子版 本人互联网数据分析师,CSDN博客专家,喜欢深入业务、也喜欢钻研技术,后续会持续更新SQL、EXCEL、统计学、PYTHON、机器学习以及业务积累相关文章,感兴趣可扫码关注喔往期推荐
Pandas数据分析实战,让你体会数据的魔力
Excel 控件+Offset组合,让图表真正动起来
掌握数据透视表8大功能,数据分析能力蹭蹭蹭!
SQL窗口函数看不明白?5大应用场景让你一步到位