关于2020年新型冠状病毒肺炎的数据分析

一、选题背景

理由

在2020年2月11日,世界卫生组织总干事谭德塞在瑞士日内瓦宣布,将新型冠状病毒感染的肺炎命名为“COVID-19”22日,国家卫生健康委发布通知,“新型冠状病毒肺炎”英文名称修订为“COVID-19”  。3月11日,世卫组织认为当前新冠肺炎疫情可被称为全球大流行 。4月4日,中国举行全国性哀悼活动,COVID-19对环境、社会和治理等方面的影响在一段时间内将持续存在。1、解COVID-19有利于个人对COVID-19的预防,及时就医,及时做好自测,2、数据的分析在生活里更容易遇到,提高相关处理能力有利于日常数据处理,3、机器学习是基于大数据的发展,选择大数据的课题,有利于理解机器学习的原理,4、较好的分析数据的能力有利于理解事物的发展规律,有利于顺应事物的发展处理问题

数据分析的预期目标

1,了解COVID-19的相关情况,感染人群特点

2,创建一个简易的预测模型,帮助预测易感染人群,做好防治,及时就医

数据来源等方面进行描述

数据来源爱数科,本文数据地址http://idatascience.cn/dataset-detail?table_id=120

二、大数据分析设计方案

1.本数据集的数据内容与数据特征分析

数据内容

数据共有10个属性的说明

字段名称字段类型字段说明
test_date 字符型 测试日期。
cough 整型 咳嗽。
fever 整型 发热。
sore_throat 整型 咽喉痛。
shortness_of_breath 整型 气促。
head_ache 整型 头痛。
corona_result 字符型 测试结果。
age_60_and_above 字符型 是否为60岁以上。
gender 字符型 性别。
test_indication 字符型 测试适应症。

 

2.数据分析的课程设计方案概述(包括实现思路与技术难点

1,数据40万数据本身较大,占用存储极大,利用第三方库pandas和 numpy处理问题

2,数据展示可以利用matplotlib和 seaborn

3,实现预测数据sklearn,最大难点就是提高正确率

三、数据分析步骤

 展示数据

1 #数据提取
2 import pandas as pd
3 csv_file="F://2020年Covid-19数据集.csv"
4 csv_data=pd.read_csv(csv_file)
5 # print(csv_data)
6 print(len(csv_data))
7 print(type(csv_data))
8 csv_data_1=csv_data
#数据初步展示 9 csv_data.head()

调整格式

 1 csv_data_1=csv_data.rename(columns={
 2     'test_date':'测试日期',
 3 'cough':'咳嗽',
 4 'fever':'发热',
 5 'sore_throat':'咽喉痛',
 6 'shortness_of_breath':'气促',
 7 'head_ache':'头痛',
 8 'corona_result':'测试结果',
 9 'age_60_and_above':'高60岁?',
10 'gender':'性别',
11 'test_indication':'测试适应症'})
12 csv_data_1.head()

1 # 查看缺少值
2 print(csv_data_1.info())
3 print("---------------------------------具体情况-----------------------------")
4 print(csv_data_1.isnull().sum())
5 print('"性别" 缺失的百分比  %.2f%%' %((csv_data_1['性别'].isnull().sum()/csv_data.shape[0])*100))
6 print('"高60岁?" 缺失的百分比  %.2f%%' %((csv_data_1['高60岁?'].isnull().sum()/csv_data.shape[0])*100))

1 # 对数据有一个明晰的情况了解,特别重要
2 #数据展示
3 for i in csv_data_1.columns:
4     print(csv_data_1[i].value_counts())
2020-09-24    7277
2020-09-23    7169
2020-09-22    7058
2020-09-29    6970
2020-09-30    6914
              ... 
2020-03-14      88
2020-03-11      76
2020-05-09      68
2020-05-16      42
2020-05-23      35
Name: 测试日期, Length: 247, dtype: int64
0    352571
1     47429
Name: 咳嗽, dtype: int64
0    346254
1     53746
Name: 发热, dtype: int64
0    378864
1     21136
Name: 咽喉痛, dtype: int64
0    392284
1      7716
Name: 气促, dtype: int64
0    357162
1     42838
Name: 头痛, dtype: int64
positive    220975
negative    179025
Name: 测试结果, dtype: int64
No     305847
Yes     44241
Name: 高60岁?, dtype: int64
male      196421
female    195827
Name: 性别, dtype: int64
Other                     293180
Contact with confirmed    103218
Abroad                      3602
Name: 测试适应症, dtype: int64
1 # 数据归一化处理
2 #检测的值 positive,Yes,male,Contact with confirmed标记为1
3 #检测的值 negative,No,female,Other标记为0
4 # Abroad标记为2
5 csv_data_1=csv_data_1.replace("positive",'1').replace("negative",'0')
6 csv_data_1=csv_data_1.replace("male",'1').replace("female",'0').replace("No",'0').replace("Yes",'1')
7 csv_data_1=csv_data_1.replace("Contact with confirmed",'1').replace("Other",'0').replace("Abroad",'2')
8 print(csv_data_1)

 1 #统计有空值的所有属性
 2 #空值本身会影响数据
 3 #把相关属性放到一个列表里
 4 def null_count(csv_data_1):
 5     lis_nul=[]
 6     for i in  csv_data_1.columns:
 7         if csv_data_1[i].isnull().value_counts()[False]!=len(csv_data_1):
 8             print('属性是:',i,"相关空值是:")
 9             print(csv_data_1[i].isnull().value_counts())
10             lis_nul.append(i)
11             print()
12     print('含有空值属性为',lis_nul)
13 null_count(csv_data_1)

1 # 空值填充为5
2 csv_data_1=csv_data_1.fillna('5')
3 null_count(csv_data_1)
4 csv_data_1.head()

 1 # 样本各属性的数据分布情况直观展示
 2 import matplotlib.pyplot as plt
 3 import matplotlib as mpl
 4 #中文设置
 5 mpl.rcParams["font.sans-serif"] = ["SimHei"]
 6 mpl.rcParams["axes.unicode_minus"] = False
 7 #数据取值
 8 axesl=plt.subplot(3,5,1)
 9 csv_data_1['性别'].value_counts().plot(kind='bar',title='性别')
10 axes2=plt.subplot(3,5,3)
11 csv_data_1['高60岁?'].value_counts().plot(kind='bar',title='高60岁?')
12 axes3=plt.subplot(3,5,5)
13 csv_data_1['测试结果'].value_counts().plot(kind='bar',title='测试结果')
14 axes4=plt.subplot(3,5,7)
15 csv_data_1['咳嗽'].value_counts().plot(kind='bar',title='咳嗽')
16 axes4=plt.subplot(3,5,9)
17 csv_data_1['发热'].value_counts().plot(kind='bar',title='发热')
18 axes4=plt.subplot(3,5,11)
19 csv_data_1['头痛'].value_counts().plot(kind='bar',title='头痛')
20 axes4=plt.subplot(3,5,13)
21 csv_data_1['气促'].value_counts().plot(kind='bar',title='气促')
22 plt.show()
23 axes4=plt.subplot(3,5,15)
24 csv_data_1['咽喉痛'].value_counts().plot(kind='bar',title='咽喉痛')
25 plt.show()
26 csv_data_1['测试适应症'].value_counts().plot(kind='bar',title='测试适应症')
27 plt.show()
28 #可以初步可视化了解数据情况
29 # 样本里性别比列较为均衡
30 # 新冠测试结果相差不大
31 # 数据集合较为可信

 1 #绘制组合柱状图(提取取值数据)上
 2 # 更直观展现数据情况
 3 
 4 #删掉无效行时间行
 5 csv_data_11=csv_data_1.drop('测试日期',axis=1)
 6 
 7 x_label=(list(csv_data_11))
 8 #建构字典处理数据
 9 lis=[]
10 a=[]
11 for i in csv_data_11:
12         lis.append(dict(zip(list(csv_data_1[i].value_counts().index),csv_data_1[i].value_counts().values)))
13 print("数据值保存为字典的列表")
14 print(lis)
15 #转字典
16 result_dict=dict(zip(x_label,lis))
17 print(result_dict)

 1 #绘制组合柱状图(绘出图片)下
 2 import matplotlib.pyplot as plt
 3 import matplotlib as mpl
 4 import numpy as np
 5 #中文设置
 6 mpl.rcParams["font.sans-serif"] = ["SimHei"]
 7 mpl.rcParams["axes.unicode_minus"] = False
 8 #数据取值
 9 x = np.arange(len(list(result_dict)))*2000
10 y = [result_dict[i][0] for i in result_dict ]
11 y1 = [result_dict[i][1] for i in result_dict ]
12 y3=[]
13 for i in result_dict:
14     if   '5'in result_dict[i] :
15         y3.append(result_dict[i]['5'])
16     else:
17         y3.append(0)
18 #属性设定
19 bar_width = 0.35*1300
20 tick_label = list(result_dict)
21 plt.bar(x, y, bar_width, align="center", color="c", label="0", alpha=0.7)
22 plt.bar(x+bar_width, y1, bar_width, color="b", align="center", label="1", alpha=0.7)
23 plt.bar(x+bar_width*2, y3, bar_width, color="y", align="center", label="空值", alpha=0.7)
24 
25 plt.title('样本数据整体分布情况')
26 plt.xlabel("检测属性")
27 plt.ylabel("数值大小")
28 plt.xticks(x+bar_width/2, tick_label)
29 # 展现图
30 plt.legend()
31 plt.show()
32 print('在粗略的统计下')
33 print("依据本图,在即便是很少的人有不适症状,依然感染新型冠状病毒的概率很大")
34 # 参考链接https://www.cnblogs.com/czz0508/p/10458425.html
35 #参数参考 https://blog.csdn.net/weixin_40343504/article/details/111935995
36 # plt.bar(x, height, width=0.8, bottom=None, *, align='center', data=None, **kwargs)
37 # x 为一个标量序列,确定x轴刻度数目
38 # height 确定y轴的刻度
39 # width 决定了柱子的宽度,仅代表形状宽度
40 # bottom 决定了柱子距离x轴的高度,默认为None,即表示与x轴距离为0
41 # align x轴上的坐标与柱体对齐的位置
42 # color 柱体的填充颜色,“r","b","g","#123465",默认“b"
43 # alpha 柱体填充颜色的透明度
44 # tick_label=labels, 每个柱体的标签名称
45 # edgecolor 柱体的边框颜色
46 # linewidth 柱体边框线的宽度

 1 # 构建线性回归模型勘察相关性(上)
 2 from sklearn.linear_model import LinearRegression
 3 #数据分离去掉结果数据  生成变量csv_data_110
 4 csv_data_110=csv_data_11.drop('测试结果',axis=1,inplace=False)
 5 # 观察变量数据情况
 6 print(csv_data_11.head())
 7 print(csv_data_110.head())
 8 #建模操作
 9 predict_model=LinearRegression()
10 predict_model.fit(csv_data_110,csv_data_11["测试结果"])
11 print('线性回归系数为:',predict_model.coef_)
12 print('线性回归截距',predict_model.intercept_)

 1 import matplotlib.pyplot as plt
 2 import numpy as np
 3 k=0
 4 for i in predict_model.coef_:
 5     x=[]
 6     for j in range(-39,40):
 7         x.append(j)
 8     plt.plot(np.array(x),np.array(x)*i+predict_model.intercept_,label=csv_data_110.columns[k])
 9     k+=1
10 plt.title("各条件与是否感染新冠的相关性曲线图")
11 plt.xlabel("各属性情况")
12 plt.ylabel('感染情况')
13 plt.legend()
14 plt.show()
15 # 可以看出年龄是否60岁对是否感染新型冠状病毒几乎没有影响,而且有些反向相关
16 # (,年轻人比较容易外出走动,加大了感染风险,)
17 # 可以看出测试适应症和发热和头疼对是否感染新型冠状病毒占了比较大的比例的相关性
18 #可以思考测试适应症、发热、头痛、咳嗽、气促、咽喉痛之间的影响

 1 from mpl_toolkits.axisartist.axislines import SubplotZero
 2 import matplotlib.pyplot as plt
 3 import numpy as np
 4 import math 
 5 mpl.rcParams["font.sans-serif"] = ["SimHei"]
 6 mpl.rcParams["axes.unicode_minus"] = False
 7 if 1:
 8     fig = plt.figure(1)
 9     ax = SubplotZero(fig, 111)
10     fig.add_subplot(ax)
11     for direction in ["xzero", "yzero"]:
12         # 轴末端加箭头
13         ax.axis[direction].set_axisline_style("-|>")
14         # 从原点添加x和y轴
15         ax.axis[direction].set_visible(True)
16     for direction in ["left", "right", "bottom", "top"]:
17         # #隐藏外框
18         ax.axis[direction].set_visible(False)
19     x = np.linspace(-2, 2., 100)
20     k=0
21     for i in predict_model.coef_:
22         ax.plot(x,x*i+predict_model.intercept_,label=csv_data_110.columns[k])
23         k+=1
24     ax.plot(x,x*(math.pi/2)+predict_model.intercept_,'--',label=("准线"))
25     ax.plot()
26     plt.legend(loc='lower right')
27     plt.show()
28 #表明斜率越大越接近于真值
29 # 推荐中文官网http://www.matplotlib.org.cn/
30 # --------------------------------------------
31 # 结合以上两图,可以得出如下思考
32 #通过比列可以试着思考,通过各属性的占比计算权值,或许加权的思想考虑预测方式
33 #------------------------------------------------------------------------

 1 # "各条件属性与感染新型冠状病毒的特征柱形图"
 2 # 展示样本数据相关情况
 3 csv_data_1
 4 import matplotlib.pyplot as plt
 5 import matplotlib as mpl
 6 import seaborn as sns
 7 h=4
 8 l=2
 9 figsize = 12,8
10 # h行l列
11 fig, axes = plt.subplots(h,l,figsize=figsize)  # 此处是一个2*2的图
12 mpl.rcParams["font.sans-serif"] = ["SimHei"]
13 mpl.rcParams["axes.unicode_minus"] = False
14 def likuai(n):
15 # 分块器 n=(a,b)
16     t=[]
17     for i in range(n[0]):
18         for j in range(n[1]):
19             t.append([i,j])
20     return t
21 a=0
22 lk=likuai((h,l))
23 for i in csv_data_11.columns.drop('测试结果')[0:h*l]:
24     sns.barplot(ax=axes[lk[a][0],lk[a][1]],y=i,x= '测试结果',data=csv_data_11,hue='性别')
25     a+=1
26 
27 plt.show()
28 # 通过(0,1)的数据值的集合,可以分析各个条件下的平均值,同样也很具有参考意义
29 # ----------数据分析--------
30 # 直观可见是否感染新冠后大概率会咳嗽,发热,咽喉痛,头疼气促
31 # 感染新冠后女性较为容易引发其他病症
32 # 男性比女性较为容易感染新冠,但几乎是同样易感染新冠的
33 # 缺失属性在【性别】和【是否60岁上】
34 # 对于年龄而言几乎与 是否60岁?无关的容易感染新冠(可能存在误差,由于缺失值的填充)
35 #有确认接触过患者感染几率是最大的
36 # -----------------------------------
37 #考虑训练预测模型时,删除这些无关条件可能会有帮助

 1 # 所有数据相对与是否感染新冠存在一定关系
 2 # 所以理论上是可以构建预测模型来预测数据的
 3 # 但是模型还会与输入样本训练的数据大小有一定的关联
 4 # 所以选择构建了数据分隔点,寻找良好的样本大小以及最大的成功率
 5 from sklearn.linear_model import LogisticRegression
 6 import pandas as pd
 7 n=[i for i in range(2,34,1)]
 8 
 9 acc0=[]
10 # 获取当不同的分隔值下模型的成功率
11 mod=[]
12 # 方便提取最优模型
13 for i in n:
14     a= i *10**4#分隔参数
15     train_data=np.array(csv_data_110[0:a])#设置为数组参数
16     train_label=np.array(csv_data_11['测试结果'][0:a])
17     test_data=np.array(csv_data_110[a:])
18     test_label=np.array(csv_data_11['测试结果'][a:])
19     from sklearn.ensemble import RandomForestClassifier
20     from xgboost import XGBClassifier
21     import numpy as np
22     #导入相关模型
23     model=LogisticRegression()
24 #     model = RandomForestClassifier()
25 #     model=XGBClassifier()
26     #训练模型
27     model.fit(train_data,train_label)
28     acc0.append(pd.Series(model.predict(test_data)-test_label).value_counts()[0]/len(model.predict(test_data)-test_label))
29     mod.append(model)
30 #测试模型
31 print('相关测试标签',model.predict(test_data))
32 print("真实标签数据",test_label)
33 print("-----------值的概率--------")
34 # 通过实打实的先预测再统计的方法得出的成功率
35 print(model.predict_proba(test_data))
36 acc=pd.Series(model.predict(test_data)-test_label).value_counts()[0]/len(model.predict(test_data)-test_label)
37 print('成功概率:',acc)
38 #搭建模型参考 https://blog.csdn.net/weixin_42299494/article/details/113652085
39 # 评估模型参考https://blog.csdn.net/weixin_39774682/article/details/111204928

 1 # 绘制相关折线图,展现数据变化情况
 2 from matplotlib import pyplot as plt
 3 #简易的极大值提取器 返回(极大值list,索引list)
 4 def mx(data):
 5     a=[]
 6     ii=[]
 7     for i in range(1,len(data)-1):
 8         if data[i]>data[i-1] and data[i]>data[i+1]:
 9             a.append(data[i])
10             ii.append(i)
11     return (a,ii)
12 mpl.rcParams["font.sans-serif"] = ["SimHei"]
13 mpl.rcParams["axes.unicode_minus"] = False
14 plt.title("取值分隔线与成功率的关系")
15 plt.xlabel("分隔位置(单位/1e4)")
16 plt.ylabel('预测的成功率')
17 plt.plot(n,acc0)
18 plt.plot([ n[i] for i in mx(acc0)[1]],mx(acc0)[0],"o",c='red')
19 plt.show()
20 #坐标字典
21 x_dic=dict(zip(mx(acc0)[0],mx(acc0)[1]))
22 print(f'极大值的坐标({max(x_dic)},{x_dic[max(x_dic)]})')
23 print(f"最优模型:{ mod[x_dic[max(x_dic)]]}")
24 #该模型还是有一定的可信度,应该还有提升的空间
25 #model1最高可信成功率可达0.7829882352941177
26 #可以思考改变模型 或者修剪数据 提高成功率

 1 # 简易的预测器
 2 # 提取最优模型
 3 model= mod[x_dic[max(x_dic)]]
 4 # 构建有趣模型函数
 5 def yuche(data,model):
 6     print("注意输入的值代表着如下对应属性是否有症状")
 7     print("    咳嗽    发热    咽喉痛    气促    头痛    高60岁?    性别    测试适应症")
 8     if model.predict([data])[0] ==1:
 9         print('预测结果为  感染')
10     else:
11         print('预测结果为  没感染')
12     print(f'预测的感染概率是{max(model.predict_proba([data])[0]):0.2f}')
13 yuche([0,0,0,0,0,1,1,0],model)
14 yuche([0,1,0,0,0,0,0,0],model)
15 yuche([0,1,0,0,1,0,1,0],model)
16 # 视乎预测模型这效果感觉还可以

# ------------------------------------------------
# 唯一的缺点就是模型准确率不是很高
# 思考如何提高模型的准确率
# 尝试不同的分类模型处理 看是否会有影响
# --------------------------------------

 

 1 # 模型绘图较为经常使用,在 以讨论不同分类函数对模型正确率是否有影响
 2 # 固 做出如下优化-------------优化-(上)----------
 3 # 注意 该数据集默认先前样本数据的方式分配
 4 from sklearn.linear_model import LogisticRegression
 5 import pandas as pd
 6 def jianmo (model):
 7     from sklearn.ensemble import RandomForestClassifier
 8     from xgboost import XGBClassifier
 9     import numpy as np
10     from sklearn.model_selection import cross_val_score
11     import numpy as np
12 # ------!!!!!1------经过多次的 建模调参 血泪教训得知-!!!!!!!!!!!!-------------------
13 # 自定义函数里放自定义函数一定一定要注意全局变量和局部变量的问题
14 # --------这里变为全局变量非常非常重要------------------------------
15 # 不设置为全局变量 直接会导致调用该函数时一直跑第一次的模型
16     global n
17     global acc0
18     global mod
19     global kacc
20 # ---------------------------
21     kacc=[]
22     n=[i for i in range(2,34,1)]
23 #     n=[3,4,5,7,9]
24     acc0=[]
25     # 获取当不同的分隔值下模型的成功率
26     mod=[]
27     # 方便提取最优模型
28 #     观察变容量的影响
29     if len(csv_data_110) !=400000:
30         print('数据总样本已改变为',len(csv_data_110))
31     for i in n:
32         a= i *10**4#分隔参数
33 #         drop_5(csv_data_110)
34 #         drop_5(csv_data_11)
35         train_data=np.array(csv_data_110[0:a])#设置为数组参数
36         train_label=np.array(csv_data_11['测试结果'][0:a])
37         test_data=np.array(csv_data_110[a:])
38         test_label=np.array(csv_data_11['测试结果'][a:])
39 
40         #导入相关模型
41 #         model = RandomForestClassifier()
42     #     model=XGBClassifier()
43         #训练模型
44         model.fit(train_data,train_label)
45         
46         scores = cross_val_score(model,test_data,test_label, cv=5, scoring='accuracy')
47         kacc.append(np.mean(scores) )
48         print( f"第{i-1}次断点,k折交叉验证accuracy为" ,np.mean(scores))
49         acc0.append(pd.Series(model.predict(test_data)-test_label).value_counts()[0]/len(model.predict(test_data)-test_label))
50         mod.append(model)
 1 # 固 做出如下优化-------------优化-(下)----------
 2 # 绘制相关折线图,展现数据变化情况
 3 def huitu(LogisticRegression):
 4     jianmo(model=LogisticRegression)
 5     from matplotlib import pyplot as plt
 6     #简易的极大值提取器 返回(极大值list,索引list)
 7     global n
 8     global acc0
 9     global mod
10     global kacc
11     def mx(data):
12         a=[]
13         ii=[]
14         for i in range(1,len(data)-1):
15             if data[i]>data[i-1] and data[i]>data[i+1]:
16                 a.append(data[i])
17                 ii.append(i)
18         return (a,ii)
19     mpl.rcParams["font.sans-serif"] = ["SimHei"]
20     mpl.rcParams["axes.unicode_minus"] = False
21     plt.title("取值分隔线与成功率的关系")
22     plt.xlabel("分隔位置(单位/1e4)")
23     plt.ylabel('预测的成功率')
24     plt.plot(n,acc0,'--',label='k折acc')
25     plt.plot(n,kacc,label='实测acc')#绘制k折acc曲线
26     plt.plot([ n[i] for i in mx(acc0)[1]],mx(acc0)[0],"o",c='red')
27     plt.legend(loc='upper left')
28     plt.show()
29     #坐标字典
30     x_dic=dict(zip(mx(acc0)[0],mx(acc0)[1]))
31 #     print(acc0)
32     print("k折交叉验证,最大成功率",max(kacc))
33     if mx(acc0)!=([], []):
34         print(f'极大值的坐标({max(x_dic)},{x_dic[max(x_dic)]})')
35         print(f"最优模型:{ mod[x_dic[max(x_dic)]]}")
36     else:
37         print('真实测得最大成功率',max(acc0))
38         print('无极值序列,请自行调节')
39     kacc=[]
40     n=[]
41     acc0=[]
42     # 获取当不同的分隔值下模型的成功率
43     mod=[]
 1 # 利用新模型处理数据
 2 import seaborn as sns
 3 import numpy as np
 4 from sklearn import linear_model
 5 from sklearn.linear_model import LogisticRegression
 6 # from sklearn.model_selection import crosscross_val_score
 7 from sklearn.model_selection import cross_val_score
 8 #构建逻辑回归模型
 9 feature=["咳嗽","发热",'气促',"头痛","高60岁?","性别"]
10 model_log=linear_model.LogisticRegression()
11 # model_log.fit(train_data,train_label)由于可以直接绘图所以注释l该处
12 LogisticRegression(C=1.0, class_weight='balanced', dual=False, fit_intercept=True,
13                   intercept_scaling=1, max_iter=10, multi_class='ovr', n_jobs=1,
14                   penalty='l2', random_state=None, solver='liblinear', tol=0.0001,
15                   verbose=1, warm_start=False)
16 huitu(model_log)
17 #solver优化算法可选newton-cg,lbfgs,liblinear,sag,saga。
18 # 参数参考链接https://blog.csdn.net/jark_/article/details/78342644

1 # 决策树分类
2 from sklearn.model_selection import cross_val_score
3 from sklearn import tree
4 dt = tree.DecisionTreeClassifier()
5 # dt.fit(train_data,train_label)
6 huitu(dt)
7 # scores = cross_val_score(dt, test_data,  test_label, cv=5, scoring='accuracy') 
8 # print(np.mean(scores))

1 # 随机森林分类
2 from sklearn import ensemble
3 rf = ensemble.RandomForestClassifier(20)
4 # rf.fit(train_data,train_label)
5 huitu(rf)

 1 #数据集合理论上,空值应该是与是否感染无关的
 2 # 尝试删掉无效行来处理是否可以提高效果 
 3 # 因为这样可以提高样本特征,感觉上会有帮助,所以尝试一下
 4 
 5 # 删掉 高60岁?为'5'的行
 6 def drop_5(csv_data_110):
 7     csv_data_110=((csv_data_110.drop(index=(csv_data_110.loc[(csv_data_110['高60岁?']=='5')].index))))
 8     print(csv_data_110[csv_data_110["高60岁?"]=='5'])
 9     print(len(csv_data_110))
10     csv_data_110=((csv_data_110.drop(index=(csv_data_110.loc[(csv_data_110['性别']=='5')].index))))
11     print(csv_data_110[csv_data_110["性别"]=='5'])
12     print(len(csv_data_110))
13     return csv_data_110
14 csv_data_110=drop_5(csv_data_110)
15 csv_data_11=drop_5(csv_data_11)
16 print(len(csv_data_110))

 展示在删掉空值情况下的成功率的变化

1 # 随机森林分类
2 from sklearn import ensemble
3 rf = ensemble.RandomForestClassifier(20)
4 # rf.fit(train_data,train_label)
5 huitu(rf)
6 # 事实证明提供的数据越多,对模型效果较好,一味删掉一些参数会影响准确性

 结果显示随机森林和决策树的效果较好一些,可以达到 78%。

附上全部完整代码

  1 #数据提取
  2 import pandas as pd
  3 csv_file="F://2020年Covid-19数据集.csv"
  4 csv_data=pd.read_csv(csv_file)
  5 # print(csv_data)
  6 print(len(csv_data))
  7 print(type(csv_data))
  8 csv_data_1=csv_data
  9 #数据初步展示
 10 csv_data.head()
 11 # ---------
 12 csv_data_1=csv_data.rename(columns={
 13      'test_date':'测试日期',
 14 'cough':'咳嗽',
 15 'fever':'发热',
 16  'sore_throat':'咽喉痛',
 17  'shortness_of_breath':'气促',
 18  'head_ache':'头痛',
 19  'corona_result':'测试结果',
 20  'age_60_and_above':'高60岁?',
 21  'gender':'性别',
 22  'test_indication':'测试适应症'})
 23 csv_data_1.head()
 24 # ---------
 25 print(csv_data_1.info())
 26 print("---------------------------------具体情况-----------------------------")
 27 print(csv_data_1.isnull().sum())
 28 print('"性别" 缺失的百分比  %.2f%%' %((csv_data_1['性别'].isnull().sum()/csv_data.shape[0])*100))
 29 print('"高60岁?" 缺失的百分比  %.2f%%' %((csv_data_1['高60岁?'].isnull().sum()/csv_data.shape[0])*100))
 30 # -------
 31 # 对数据有一个明晰的情况了解,特别重要
 32 #数据展示
 33 for i in csv_data_1.columns:
 34      print(csv_data_1[i].value_counts())
 35 # ------
 36 1 # 数据归一化处理
 37 2 #检测的值 positive,Yes,male,Contact with confirmed标记为1
 38 3 #检测的值 negative,No,female,Other标记为0
 39 4 # Abroad标记为2
 40 csv_data_1=csv_data_1.replace("positive",'1').replace("negative",'0')
 41 csv_data_1=csv_data_1.replace("male",'1').replace("female",'0').replace("No",'0').replace("Yes",'1')
 42 csv_data_1=csv_data_1.replace("Contact with confirmed",'1').replace("Other",'0').replace("Abroad",'2')
 43 print(csv_data_1)
 44 # --------
 45 def null_count(csv_data_1):
 46      lis_nul=[]
 47      for i in  csv_data_1.columns:
 48           if csv_data_1[i].isnull().value_counts()[False]!=len(csv_data_1):
 49               print('属性是:',i,"相关空值是:")
 50               print(csv_data_1[i].isnull().value_counts())
 51               lis_nul.append(i)
 52               print()
 53      print('含有空值属性为',lis_nul)
 54 null_count(csv_data_1)
 55 # -----
 56 # 空值填充为5
 57 csv_data_1=csv_data_1.fillna('5')
 58 null_count(csv_data_1)
 59 csv_data_1.head()
 60 # -------
 61 # 样本各属性的数据分布情况直观展示
 62 import matplotlib.pyplot as plt
 63 import matplotlib as mpl
 64 #中文设置
 65 mpl.rcParams["font.sans-serif"] = ["SimHei"]
 66 mpl.rcParams["axes.unicode_minus"] = False
 67 #数据取值
 68 axesl=plt.subplot(3,5,1)
 69 csv_data_1['性别'].value_counts().plot(kind='bar',title='性别')
 70 axes2=plt.subplot(3,5,3)
 71 csv_data_1['高60岁?'].value_counts().plot(kind='bar',title='高60岁?')
 72 axes3=plt.subplot(3,5,5)
 73 csv_data_1['测试结果'].value_counts().plot(kind='bar',title='测试结果')
 74 axes4=plt.subplot(3,5,7)
 75 csv_data_1['咳嗽'].value_counts().plot(kind='bar',title='咳嗽')
 76 axes4=plt.subplot(3,5,9)
 77 csv_data_1['发热'].value_counts().plot(kind='bar',title='发热')
 78 axes4=plt.subplot(3,5,11)
 79 csv_data_1['头痛'].value_counts().plot(kind='bar',title='头痛')
 80 axes4=plt.subplot(3,5,13)
 81 csv_data_1['气促'].value_counts().plot(kind='bar',title='气促')
 82 plt.show()
 83 axes4=plt.subplot(3,5,15)
 84 csv_data_1['咽喉痛'].value_counts().plot(kind='bar',title='咽喉痛')
 85 plt.show()
 86 csv_data_1['测试适应症'].value_counts().plot(kind='bar',title='测试适应症')
 87 plt.show()
 88 # -------
 89 csv_data_11=csv_data_1.drop('测试日期',axis=1)
 90 x_label=(list(csv_data_11))
 91 #建构字典处理数据
 92 lis=[]
 93 a=[]
 94 for i in csv_data_11:
 95     if 0 not in list(csv_data_1[i].value_counts().index):
 96 # #
 97        lis.append(dict(zip(list(csv_data_1[i].value_counts().index),csv_data_1[i].value_counts().values)))
 98 print("数据值保存为字典的列表")
 99 print(lis)
100 #转字典
101 result_dict=dict(zip(x_label,lis))
102 print(result_dict)
103 # ------
104 #绘制组合柱状图(绘出图片)下
105 import matplotlib.pyplot as plt
106 import matplotlib as mpl
107 import numpy as np
108 #中文设置
109 mpl.rcParams["font.sans-serif"] = ["SimHei"]
110 mpl.rcParams["axes.unicode_minus"] = False
111 #数据取值
112 x = np.arange(len(list(result_dict)))*2000
113 # 有时候字典的key是int 有的时候是str类型 需要灵活更改
114 y = [result_dict[i]['0'] for i in result_dict ]
115 y1 = [result_dict[i]['1'] for i in result_dict ]
116 y3=[]
117 for i in result_dict:
118     if   '5'in result_dict[i] :
119        y3.append(result_dict[i]['5'])
120     else:
121         y3.append(0)
122 #属性设定
123 bar_width = 0.35*1300
124 tick_label = list(result_dict)
125 plt.bar(x, y, bar_width, align="center", color="c", label="0", alpha=0.7)
126 plt.bar(x+bar_width, y1, bar_width, color="b", align="center", label="1", alpha=0.7)
127 plt.bar(x+bar_width*2, y3, bar_width, color="y", align="center", label="空值", alpha=0.7)
128 
129 plt.title('样本数据整体分布情况')
130 plt.xlabel("检测属性")
131 plt.ylabel("数值大小")
132 plt.xticks(x+bar_width/2, tick_label)
133 # 展现图
134 plt.legend()
135 plt.show()
136 print('在粗略的统计下')
137 print("依据本图,在即便是很少的人有不适症状,依然感染新型冠状病毒的概率很大")
138 # -------
139 # 构建线性回归模型勘察相关性(上)
140 from sklearn.linear_model import LinearRegression
141 #数据分离去掉结果数据  生成变量csv_data_110
142 csv_data_110=csv_data_11.drop('测试结果',axis=1,inplace=False)
143 # 观察变量数据情况
144 print(csv_data_11.head())
145 print(csv_data_110.head())
146 #建模操作
147 predict_model=LinearRegression()
148 predict_model.fit(csv_data_110,csv_data_11["测试结果"])
149 print('线性回归系数为:',predict_model.coef_)
150 print('线性回归截距',predict_model.intercept_)
151 # --------
152 # 构建线性回归模型勘察相关性(中)
153 from sklearn.linear_model import LinearRegression
154 import matplotlib.pyplot as plt
155 import numpy as np
156 k=0
157 for i in predict_model.coef_:
158     x=[]
159     for j in range(-39,40):
160         x.append(j)
161     plt.plot(np.array(x),np.array(x)*i+predict_model.intercept_,label=csv_data_110.columns[k])
162     k+=1
163 plt.title("各条件与是否感染新冠的相关性曲线图")
164 plt.xlabel("各属性情况")
165 plt.ylabel('感染情况')
166 plt.legend()
167 plt.show()
168 # -----带准线的斜率图-------
169 from mpl_toolkits.axisartist.axislines import SubplotZero
170 import matplotlib.pyplot as plt
171 import numpy as np
172 import math
173 mpl.rcParams["font.sans-serif"] = ["SimHei"]
174 mpl.rcParams["axes.unicode_minus"] = False
175 if 1:
176     fig = plt.figure(1)
177     ax = SubplotZero(fig, 111)
178     fig.add_subplot(ax)
179     for direction in ["xzero", "yzero"]:
180         # 轴末端加箭头
181         ax.axis[direction].set_axisline_style("-|>")
182         # 从原点添加x和y轴
183         ax.axis[direction].set_visible(True)
184     for direction in ["left", "right", "bottom", "top"]:
185         # #隐藏外框
186         ax.axis[direction].set_visible(False)
187     x = np.linspace(-2, 2., 100)
188     k=0
189     for i in predict_model.coef_:
190         ax.plot(x,x*i+predict_model.intercept_,label=csv_data_110.columns[k])
191         k+=1
192     ax.plot(x,x*(math.pi/2)+predict_model.intercept_,'--',label=("准线"))
193     ax.plot()
194     plt.legend(loc='lower right')
195     plt.show()
196 #------------------------------------------------------------------------
197 # "各条件属性与感染新型冠状病毒的特征柱形图"
198 # 展示样本数据相关情况
199 csv_data_1
200 import matplotlib.pyplot as plt
201 import matplotlib as mpl
202 import seaborn as sns
203 h=4
204 l=2
205 figsize = 12,8
206 # h行l列
207 fig, axes = plt.subplots(h,l,figsize=figsize)  # 此处是一个2*2的图
208 mpl.rcParams["font.sans-serif"] = ["SimHei"]
209 mpl.rcParams["axes.unicode_minus"] = False
210 def likuai(n):
211 # 分块器 n=(a,b)
212     t=[]
213     for i in range(n[0]):
214         for j in range(n[1]):
215             t.append([i,j])
216     return t
217 a=0
218 lk=likuai((h,l))
219 for i in csv_data_11.columns.drop('测试结果')[0:h*l]:
220     sns.barplot(ax=axes[lk[a][0],lk[a][1]],y=i,x= '测试结果',data=csv_data_11,hue='性别')
221     a+=1
222 
223 plt.show()
224 # ----------构建预测模型--------
225 # 所有数据相对与是否感染新冠存在一定关系-------------------------断点绘图(上)------------------------
226 # 所以理论上是可以构建预测模型来预测数据的
227 from sklearn.linear_model import LogisticRegression
228 import pandas as pd
229 n=[i for i in range(2,34,1)]
230 acc0=[]
231 # 获取当不同的分隔值下模型的成功率
232 mod=[]
233 # 方便提取最优模型
234 for i in n:
235     a= i *10**4#分隔参数
236     train_data=np.array(csv_data_110[0:a])#设置为数组参数
237     train_label=np.array(csv_data_11['测试结果'][0:a])
238     test_data=np.array(csv_data_110[a:])
239     test_label=np.array(csv_data_11['测试结果'][a:])
240     from sklearn.ensemble import RandomForestClassifier
241     from xgboost import XGBClassifier
242     import numpy as np
243     #导入相关模型
244     model=LogisticRegression()
245 #     model = RandomForestClassifier()
246 #     model=XGBClassifier()
247     #训练模型
248     model.fit(train_data,train_label)
249     acc0.append(pd.Series(model.predict(test_data)-test_label).value_counts()[0]/len(model.predict(test_data)-test_label))
250     mod.append(model)
251 #测试模型
252 print('相关测试标签',model.predict(test_data))
253 print("真实标签数据",test_label)
254 print("-----------值的概率--------")
255 # 通过实打实的先预测再统计的方法得出的成功率
256 print(model.predict_proba(test_data))
257 acc=pd.Series(model.predict(test_data)-test_label).value_counts()[0]/len(model.predict(test_data)-test_label)
258 print('成功概率:',acc)
259 # ---------
260 # 绘制相关折线图,展现数据变化情况-------------断点绘图(下)------------------------------
261 from matplotlib import pyplot as plt
262 #简易的极大值提取器 返回(极大值list,索引list)
263 def mx(data):
264     a=[]
265     ii=[]
266     for i in range(1,len(data)-1):
267         if data[i]>data[i-1] and data[i]>data[i+1]:
268             a.append(data[i])
269             ii.append(i)
270     return (a,ii)
271 mpl.rcParams["font.sans-serif"] = ["SimHei"]
272 mpl.rcParams["axes.unicode_minus"] = False
273 plt.title("取值分隔线与成功率的关系")
274 plt.xlabel("分隔位置(单位/1e4)")
275 plt.ylabel('预测的成功率')
276 plt.plot(n,acc0)
277 plt.plot([ n[i] for i in mx(acc0)[1]],mx(acc0)[0],"o",c='red')
278 plt.show()
279 #坐标字典
280 x_dic=dict(zip(mx(acc0)[0],mx(acc0)[1]))
281 print(f'极大值的坐标({max(x_dic)},{x_dic[max(x_dic)]})')
282 print(f"最优模型:{ mod[x_dic[max(x_dic)]]}")
283 # --------------
284 # 简易的预测器
285 # 提取最优模型
286 model= mod[x_dic[max(x_dic)]]
287 # 构建有趣模型函数
288 def yuche(data,model):
289     print("注意输入的值代表着如下对应属性是否有症状")
290     print("    咳嗽    发热    咽喉痛    气促    头痛    高60岁?    性别    测试适应症")
291     if model.predict([data])[0] ==1:
292         print('预测结果为  感染')
293     else:
294         print('预测结果为  没感染')
295     print(f'预测的感染概率是{max(model.predict_proba([data])[0]):0.2f}')
296 yuche([0,0,0,0,0,1,1,0],model)
297 yuche([0,1,0,0,0,0,0,0],model)
298 yuche([0,1,0,0,1,0,1,0],model)
299 # 视乎预测模型这效果感觉还可以
300 # --------
301 # 固 做出如下优化-------------优化-(上)----------
302 # 注意 该数据集默认先前样本数据的方式分配
303 from sklearn.linear_model import LogisticRegression
304 import pandas as pd
305 def jianmo(model):
306     from sklearn.ensemble import RandomForestClassifier
307     from xgboost import XGBClassifier
308     import numpy as np
309     from sklearn.model_selection import cross_val_score
310     import numpy as np
311     # ------!!!!!1------经过多次的 建模调参 血泪教训得知-!!!!!!!!!!!!-------------------
312     # 自定义函数里放自定义函数一定一定要注意全局变量和局部变量的问题
313     # --------这里变为全局变量非常非常重要------------------------------
314     # 不设置为全局变量 直接会导致调用该函数时一直跑第一次的模型
315     global n
316     global acc0
317     global mod
318     global kacc
319     # ---------------------------
320     kacc = []
321     n = [i for i in range(2, 34, 1)]
322     #     n=[3,4,5,7,9]
323     acc0 = []
324     # 获取当不同的分隔值下模型的成功率
325     mod = []
326     # 方便提取最优模型
327     #     观察变容量的影响
328     if len(csv_data_110) != 400000:
329         print('数据总样本已改变为', len(csv_data_110))
330     for i in n:
331         a = i * 10 ** 4  # 分隔参数
332         #         drop_5(csv_data_110)
333         #         drop_5(csv_data_11)
334         train_data = np.array(csv_data_110[0:a])  # 设置为数组参数
335         train_label = np.array(csv_data_11['测试结果'][0:a])
336         test_data = np.array(csv_data_110[a:])
337         test_label = np.array(csv_data_11['测试结果'][a:])
338 
339         # 导入相关模型
340         #         model = RandomForestClassifier()
341         #     model=XGBClassifier()
342         # 训练模型
343         model.fit(train_data, train_label)
344 
345         scores = cross_val_score(model, test_data, test_label, cv=5, scoring='accuracy')
346         kacc.append(np.mean(scores))
347         print(f"第{i - 1}次断点,k折交叉验证accuracy为", np.mean(scores))
348         acc0.append(pd.Series(model.predict(test_data) - test_label).value_counts()[0] / len(
349             model.predict(test_data) - test_label))
350         mod.append(model)
351 # -------
352 # 固 做出如下优化-------------优化-(下)----------
353 # 绘制相关折线图,展现数据变化情况
354 def huitu(LogisticRegression):
355     jianmo(model=LogisticRegression)
356     from matplotlib import pyplot as plt
357     #简易的极大值提取器 返回(极大值list,索引list)
358     global n
359     global acc0
360     global mod
361     global kacc
362     def mx(data):
363         a=[]
364         ii=[]
365         for i in range(1,len(data)-1):
366             if data[i]>data[i-1] and data[i]>data[i+1]:
367                 a.append(data[i])
368                 ii.append(i)
369         return (a,ii)
370     mpl.rcParams["font.sans-serif"] = ["SimHei"]
371     mpl.rcParams["axes.unicode_minus"] = False
372     plt.title("取值分隔线与成功率的关系")
373     plt.xlabel("分隔位置(单位/1e4)")
374     plt.ylabel('预测的成功率')
375     plt.plot(n,acc0,'--',label='k折acc')
376     plt.plot(n,kacc,label='实测acc')#绘制k折acc曲线
377     plt.plot([ n[i] for i in mx(acc0)[1]],mx(acc0)[0],"o",c='red')
378     plt.legend(loc='upper left')
379     plt.show()
380     #坐标字典
381     x_dic=dict(zip(mx(acc0)[0],mx(acc0)[1]))
382 #     print(acc0)
383     print("k折交叉验证,最大成功率",max(kacc))
384     if mx(acc0)!=([], []):
385         print(f'极大值的坐标({max(x_dic)},{x_dic[max(x_dic)]})')
386         print(f"最优模型:{ mod[x_dic[max(x_dic)]]}")
387     else:
388         print('真实测得最大成功率',max(acc0))
389         print('无极值序列,请自行调节')
390     kacc=[]
391     n=[]
392     acc0=[]
393     # 获取当不同的分隔值下模型的成功率
394     mod=[]
395 # ------
396 # 利用新模型处理数据
397 import seaborn as sns
398 import numpy as np
399 from sklearn import linear_model
400 from sklearn.linear_model import LogisticRegression
401 # from sklearn.model_selection import crosscross_val_score
402 from sklearn.model_selection import cross_val_score
403 #构建逻辑回归模型
404 feature=["咳嗽","发热",'气促',"头痛","高60岁?","性别"]
405 model_log=linear_model.LogisticRegression()
406 # model_log.fit(train_data,train_label)由于可以直接绘图所以注释l该处
407 LogisticRegression(C=1.0, class_weight='balanced', dual=False, fit_intercept=True,
408                   intercept_scaling=1, max_iter=10, multi_class='ovr', n_jobs=1,
409                   penalty='l2', random_state=None, solver='liblinear', tol=0.0001,
410                   verbose=1, warm_start=False)
411 huitu(model_log)
412 # -----
413 # 决策树分类
414 from sklearn.model_selection import cross_val_score
415 from sklearn import tree
416 dt = tree.DecisionTreeClassifier()
417 huitu(dt)
418 # -----
419 # 随机森林分类
420 from sklearn import ensemble
421 rf = ensemble.RandomForestClassifier(20)
422 # rf.fit(train_data,train_label)
423 huitu(rf)
424 # ------
425 # 删掉 高60岁?为'5'的行
426 def drop_5(csv_data_110):
427     csv_data_110=((csv_data_110.drop(index=(csv_data_110.loc[(csv_data_110['高60岁?']=='5')].index))))
428     print(csv_data_110[csv_data_110["高60岁?"]=='5'])
429     print(len(csv_data_110))
430     csv_data_110=((csv_data_110.drop(index=(csv_data_110.loc[(csv_data_110['性别']=='5')].index))))
431     print(csv_data_110[csv_data_110["性别"]=='5'])
432     print(len(csv_data_110))
433     return csv_data_110
434 csv_data_110=drop_5(csv_data_110)
435 csv_data_11=drop_5(csv_data_11)
436 print(len(csv_data_110))
437 # -------
438 # 随机森林分类
439 from sklearn import ensemble
440 rf = ensemble.RandomForestClassifier(20)
441 # rf.fit(train_data,train_label)
442 huitu(rf)
443 # 事实证明提供的数据越多,对模型效果较好

四、总结

1.通过对数据分析和挖掘,得到哪些有益的结论?是否达到预期的目标?

新冠病毒极大情况下依赖于接触传播,感染后患咳嗽,发热,咽喉痛,头疼,气促的症状显著升高,病毒不会管你是男是女,年纪大还是年纪小。基本达到预期目标,成功构建了预测模型。稍稍优化了一下。

2.自己在完成此设计过程中,得到哪些收获?以及要改进的建议

对数据的分析很重要,良好的数据分析有利于快速的选择较好的算法模型,同时进一步加深了机器学习的理解,最大的收获就是深刻体验了一下函数套函数,局部变量和全局变量的处理问题。没有很好的处理它们的关系,将引发一系列问题。 模型还有提升的空间,还可以继续思考如何提高模型的正确率,还有提升的空间,继续学习的方向。

posted @ 2021-12-28 19:18  掉队了的云朵朵  阅读(364)  评论(0编辑  收藏  举报