首页 > 其他分享 >大数据分析——外国人群薪资收入数据分析与挖掘

大数据分析——外国人群薪资收入数据分析与挖掘

时间:2022-12-21 21:56:37浏览次数:64  
标签:数据分析 plt ## res 挖掘 ls 薪资 033 data

大数据分析——外国人群薪资收入数据分析与挖掘

一、   选题背景

  人群收入是大众关心的非常重要的经济生活话题,然而人群收入受很多方面的因素影响,有年龄因素、工作性质因素、国家来源因素以及每周工作时长因素等等。根据统计和经济学知识,这些因素确实是跟收入有一定关系的,所以我们这里涉及的预测自变量有15个相关的指标,当然为了保护人群的隐私数据,很大部分数据值都存在脱敏处理,但这并不代表我们不能运用这些信息,重新运用这些信息是需要相应的转换和数据分析的。本文就是基于机器学习技术来预测和分析我们所需要的人群收入内在价值信息,通过内在信息做到对人群信息的掌握,从而统筹好社会发展。

二、   大数据分析设计方案

1.本数据集的数据内容

  本数据集是一份外国人群数的相关收入信息数据,含有15个字段,数据共计30000多条。

数据特征分析

字段:解释

Age: 年龄

Work Class: 工作类型

Final Weight: 体重

Education : 教育程度

Education Number: 教育年限

Marital Status: 婚姻状态

Occupation: 职业

Relationship:社会关系

Race: 种族

Sex: 性别

Capital Gain: 资本收益

Capital Loss: 资本损失

Hours per Week: 周工时

Country: 国家

Income: 收入

2.数据分析的课程设计方案概述

(1)    先对数据进行预处理和清洗

(2)    利用数据建模与挖掘进行数据分析

(3)    数据的特征工程与可视化

三、数据分析步骤

1.数据源

  数据集来源于国外Kaggle数据集网站进行采集。源数据集网址

  https://www.kaggle.com/datasets/jack20216915/population-income?select=income.xlsx

导入包和数据集

 1 import matplotlib.pyplot as plt
 2 import seaborn as sns
 3 import pandas as pd
 4 import numpy as np
 5 import time
 6 import warnings
 7 warnings.filterwarnings('ignore')
 8 start_time = time.time()
 9 plt.rcParams['font.sans-serif']=['SimHei']##中文乱码问题!
10 plt.rcParams['axes.unicode_minus']=False#横坐标负号显示问题!
11 path = 'income.xlsx'
12 data = pd.read_excel(path )
13 colstr = ['workclass','education','marital-status','occupation','relationship','race','sex',
14           'native-country','income']
15 data

2数据清洗

  数据清洗是建模非常重要的组成部分,能对后续建模起到事半功倍的效果。在工程实践中,我们得到的数据会存在有缺失值、重复值等,在使用之前需要进行数据清洗。

(1)删除无效id列

1 data.drop('id',axis=1,inplace=True)
2 data.head()

(2)稀疏值处理

  明显地发现,“资本收益”序列数数存在明显的稀疏情况(0的个数占比92%),“资本损失”也是(0的个数占比95%),稀疏数据的大量存在一方面导致运算复杂,另一方面会对模型造成过拟合现象,去除这两列数据。最终处理结果如下:

1 del data['capital-gain']
2 del data['capital-loss']
3 data

(3)数据类型转换,删除缺失值

  先对数据的缺失值进行删除(缺失值不是很多),由于本身数据很多字段对应的值为字符串数据,但是字符串数据是不能参与运算的,可是我们还非常想充分利用此数据集,所以将字符串数据改写为类别数值数据。

 1 def transform_type(data,col):##转换数据类型
 2 
 3     print('original:',data.shape)
 4     data = data.dropna()
 5     print('now:',data.shape)
 6 
 7     for i in col:
 8         datatemp = data[i]
 9         msg = set(datatemp)
10         for j,k in zip(msg,[l for l in range(1,len(msg) + 1)]):
11             data[i][data[i]==j] = k
12     return data
13 res = transform_type(data,colstr)
14 
15 res.index = [i for i in range(res.shape[0])]
16 index_ls = res.index
17 print(res)

 (4)异常值处理

  采用多项式拟合+统计方法来处理,但不处理类别数据,只对连续型数据(排除“年龄”和“教育年限”,这两列数据非常常规不做处理)做处理。

 1 def substitute_outliner(data,original_ls,yl,tit,mul1,mul2,num_ls):
 2     print('\033[1;34m{0:*^80}\033[1;0m'.format('特征数据“%s”异常值处理'%yl))
 3     copydata = original_ls.copy()
 4     for i in data[5]:##获取异常值位置
 5         del original_ls[i]##按照位置删除最最保险
 6         upvalue = data[2][i]
 7         downvalue = data[3][i]
 8         originalvalue = copydata[i]
 9         if originalvalue <= downvalue:
10             changevaluetemp = downvalue * 0.5 + upvalue * 0.25
11             if changevaluetemp >= upvalue:
12                 changevalue = upvalue
13             else:
14                 changevalue = max(changevaluetemp,downvalue)##最小不低于downvalue,防止upvalue过小
15             original_ls.insert(i,round(changevalue,1))
16             print('\033[1;31m异常数据编号为(原始值%s):%s,替换的修正值为:%s,downvalue:%s\033[0m' % (originalvalue, num_ls[i], round(changevalue,2),round(downvalue,2)))
17         if originalvalue >= upvalue:
18             changevaluetemp = upvalue * 0.5 + downvalue * 0.25
19             if changevaluetemp <= downvalue:
20                 changevalue = downvalue
21             else:
22                 changevalue = min(changevaluetemp,upvalue)##最大不超过upvalue,防止downvalue过大
23             original_ls.insert(i,round(changevalue,1))
24             print('\033[1;31m异常数据编号为(原始值%s):%s,替换的修正值为:%s,upvalue:%s\033[0m'%(originalvalue,num_ls[i],round(changevalue,2),round(upvalue,2)))
25 
26     plt.figure(figsize=(15, 8))
27     plt.plot(list(copydata), 'y', label='原始数值')
28     plt.plot(data[1], 'r', label='拟合曲线')
29     plt.plot(data[2], 'purple', label='拟合上限(%ssigm)曲线'%mul1)
30     plt.plot(data[3], 'b', label='拟合下限(%ssigm)曲线'%mul2)
31     plt.plot(original_ls, 'g', label='处理完后的数据')
32     plt.legend(fontsize=15)
33     plt.tick_params(labelsize=15)
34     plt.xlabel('编号',fontsize=18)
35     plt.ylabel(yl,fontsize=18)
36     plt.title(tit,fontsize=20)
37     plt.show()
38     return original_ls
39 
40 def check_outlier(value,mul1,mul2,yl):
41 
42     print('\033[1;34m{0:*^80}\033[1;0m'.format('特征数据“%s”预处理'%yl))
43     x = [j for j in range(len(value))]
44     coeffs = np.polyfit(x, value, 10)  ##专门求多项式估计参数的函数,根据实际数据波动取相应的阶数
45     p = np.poly1d(coeffs)  # 一元估计参数
46     sigm = p(x).std()
47     sigm_up = p(x) + mul1 * sigm
48     sigm_down = p(x) - mul2 * sigm
49     outliner = value[(value < sigm_down) | (value > sigm_up)]#条件筛选
50     print('\033[1;31m原数据长度:%s,异常数据:%s\033[0m'%(len(value),len(outliner)))
51     print(outliner)
52     return list(outliner),p(x),sigm_up,sigm_down,x,list(outliner.index)
53 
54 col = list(res)
55 remove_ls = colstr + ['age','education-num']
56 
57 for i in remove_ls:
58     col.remove(i)##类别数据不作处理
59 for i in col:##性别和编号不做计算
60     mul1 = 500
61     mul2 = 500##由于数据很大是人为的,这里mul1和mul2参数慎改
62     res1 = check_outlier(res[i],mul1,mul2,i)
63     res2 = substitute_outliner(res1,list(res[i]),i,'“%s”数据预处理图'%i,mul1,mul2,index_ls)
64     res[i] = res2##数据替换
65 
66 del res['capital-gain']
67 del res['capital-loss']
68 del res['education']
69 # res.to_excel(path + '处理好的数据.xlsx')

 

 

3大数据分析过程及采用的算法

  我们主要是利用逻辑回归做预测,因为这种模型在处理二分类上有很好的效果,泛化能力强,过拟合概率低。我们开始先对数据集进行训练集:测试集=7:3的比例的随机选取,然后确定好模型的随机种子、其它相关参数等,多次调整取最优,最终给出评价指标来综合评价预测模型的效果。

  评价指标我们主要给出六种,一是模型的准确率指标,二是混淆矩阵可视化图,三是ROC修正后的评价指标,四是召回率,五是精准率,六是F1值。

  但是为了最终客观评价模型的性能,一次随机实验是不够的,我们将多次实验,取各个指标的平均结果,最为最后的评价指标。

(1)  逻辑回归模型原理

实现代码

  1 from sklearn.metrics import roc_curve, auc,confusion_matrix,f1_score, precision_score, recall_score
  2 from sklearn.linear_model import LogisticRegression as LR
  3 from sklearn.model_selection import train_test_split
  4 import matplotlib.pyplot as plt
  5 import pandas as pd
  6 import numpy as np
  7 
  8 import warnings
  9 warnings.filterwarnings('ignore')
 10 
 11 
 12 plt.rcParams['font.sans-serif']=['SimHei']##中文乱码问题!
 13 plt.rcParams['axes.unicode_minus']=False#横坐标负号显示问题!
 14 
 15 
 16 data = pd.read_excel('处理好的数据.xlsx',index_col=0)
 17 print(data)
 18 
 19 
 20 # del data['fnlwgt']##去除“体重”变量
 21 data.iloc[:,1:data.shape[1]-1] = (data.iloc[:,1:data.shape[1]-1] - data.iloc[:,1:data.shape[1]-1].min()) \
 22                                  / (data.iloc[:,1:data.shape[1]-1].max() - data.iloc[:,1:data.shape[1]-1].min())
 23 X = np.array(data.iloc[:,1:data.shape[1]-1])##自变量的读取
 24 
 25 Y = np.array(data.iloc[:,data.shape[1]-1])##因变量的读取
 26 dis_name = [1,2]
 27 rd = 211
 28 
 29 
 30 ##绘制roc图
 31 def make_figure_auc_roc(true_label,score,class_):
 32     plt.figure(figsize=(15, 8))
 33 
 34     fpr, tpr, thresholds = roc_curve(true_label,score,pos_label=class_,drop_intermediate=False)
 35     ###返回的是一系列thresholds阈值
 36     roc_auc = auc(fpr, tpr)
 37     roc_result = pd.DataFrame({'fpr' : fpr,'tpr' : tpr, 'tf' : tpr - (1-fpr),'thresholds' : thresholds})
 38 #     roc_result.iloc[(roc_result.tf-0).abs().argsort()[:1]]
 39     optimal_idx = np.argmax(tpr - fpr)
 40     optimal_threshold = thresholds[optimal_idx]
 41     y = tpr[optimal_idx]
 42     x = fpr[optimal_idx]
 43     plt.figure(figsize=(8,5))
 44     plt.plot(fpr, tpr, color='navy',label='AUC=%.3f' % roc_auc)
 45     plt.plot([-0.005, 1.005], [-0.005, 1.005], color='orange',linestyle='--')
 46     plt.xlabel('1-特异度',fontsize=10)
 47     plt.ylabel('敏感度',fontsize=10)
 48     plt.scatter(x, y, c='red',s=15)
 49     plt.tick_params(labelsize=12,rotation=10)
 50     plt.title('ROC曲线',fontsize=12)
 51     plt.legend(loc='best',fontsize=18)
 52     plt.text(x+0.05,y-0.05,s='('+str(round(1-x, 3))+', '+str(round(y, 3))+')',fontsize=15)
 53     plt.show()
 54     return roc_auc
 55 
 56 def cm_plot(yp, y):##混淆矩阵
 57     plt.figure(figsize=(15, 8))
 58     cm = confusion_matrix(yp, y)  # 混淆矩阵
 59     plt.matshow(cm, cmap=plt.cm.Greens)  # 画混淆矩阵图,配色风格使用cm.Greens,更多风格请参考官网。
 60     plt.colorbar()  # 颜色标签
 61 
 62     for x in range(len(cm)):  # 数据标签
 63         for y in range(len(cm)):
 64             plt.annotate(cm[x, y], xy=(x, y), horizontalalignment='center', verticalalignment='center')
 65     plt.ylabel('真实标签',fontsize=10)  # 坐标轴标签
 66     plt.xlabel('预测标签',fontsize=10)  # 坐标轴标签
 67     plt.title('预测混淆矩阵图', fontsize=12)
 68     plt.show()
 69 
 70 ##自定义准确率计算
 71 def show_result(dis_name, pre_ls, real_ls,rd):##准确率
 72 
 73     ls_r = []
 74     ls_c = []
 75     for d in dis_name:
 76         res_ls = []
 77         for i, j in zip(pre_ls, list(real_ls)):
 78             if i == j == d:
 79                 res_ls.append('正确')
 80 
 81         ls_r.append(len(res_ls) / list(real_ls).count(d))
 82         ls_c.append((len(res_ls),list(real_ls).count(d)))
 83 
 84         print('\033[1;32m随机种子是%s时,%s(%s/%s)准确率:%.3f%%\033[0m' % (rd,d, len(res_ls), list(real_ls).count(d), len(res_ls) / list(real_ls).count(d) * 100))
 85 
 86     res_ls = []
 87     for i, j in zip(pre_ls, list(real_ls)):
 88         if i == j:
 89             res_ls.append('正确')
 90         else:
 91             res_ls.append('错误')
 92 
 93     print('\033[1;31m随机种子是%s时,总预测(%s/%s)准确率:%.3f%%\033[0m' % (rd,res_ls.count('正确'), len(res_ls), res_ls.count('正确') / len(res_ls) * 100))
 94     df = pd.DataFrame([list(real_ls), pre_ls, res_ls], index=['真实', '预测', '预测结果']).T
 95     allcorretrate = res_ls.count('正确') / len(res_ls) * 100
 96     return df,allcorretrate
 97 
 98 
 99 ##建立LR模型
100 def model(x,y,rd=rd):
101 
102     xtrain, xtest, ytrain, ytest = train_test_split(x, y, test_size=0.3, random_state=rd)
103     lr = LR(solver='liblinear')  # 建立逻辑回归模型
104     lr.fit(xtrain, ytrain)  # 用特征数据来训练模型
105     pre_lr = lr.predict(xtest)
106     pro_lr = lr.predict_proba(xtest)
107 
108     return pre_lr,ytest,pro_lr,lr.classes_[0]
109 
110 print('\033[1;38m{0:*^80}\033[0m'.format('一次实验随机种子为%s的准确率汇总'%rd))
111 
112 res = model(X,Y)
113 make_figure_auc_roc(res[1], res[2][:, 0], res[3])
114 cm_plot(res[0],res[1])
115 show_result(dis_name,res[0],res[1],rd)
116 
117 f1 = round(f1_score(res[1], res[0], average='macro'),3)##F计算
118 p = round(precision_score(res[1], res[0], average='macro'),3)##精准率计算
119 r = round(recall_score(res[1], res[0], average='macro'),3)##召回率计算
120 print(f1,p,r)
121 
122 
123 ##循环调用LR模型并可视化结果
124 
125 def makefigure(rdls,x,y,func,dn):
126 
127     plt.figure(figsize=(15, 8))
128     print('\033[1;38m{0:*^80}\033[0m'.format('多次实验的准确率汇总'))
129     lsr = []
130     f1_ls = []
131     p_ls = []
132     r_ls = []
133     rou_ls = []
134     for k in rdls:
135         R = func(x,y,k)##循环调用模型
136         rr = show_result(dn, R[0], R[1],k)
137         f1 = f1_score(R[1], R[0], average='macro')
138         p = precision_score(R[1], R[0], average='macro')
139         r = recall_score(R[1], R[0], average='macro')
140         roc = make_figure_auc_roc(R[1], R[2][:, 0], R[3])
141         f1_ls.append(f1)
142         p_ls.append(p)
143         r_ls.append(r)
144         lsr.append(rr[1])
145         rou_ls.append(roc)
146     plt.figure(figsize=(15, 8))
147     print('\033[1;38m平均准确率:%.3f%%\033[0m'%(pd.Series(lsr).mean()))
148     print('\033[1;38m平均f1值:%.3f\033[0m' % (pd.Series(f1_ls).mean()))
149     print('\033[1;38m平均召回率值:%.3f\033[0m' % (pd.Series(p_ls).mean()))
150     print('\033[1;38m平均精准率值:%.3f\033[0m' % (pd.Series(r_ls).mean()))
151     print('\033[1;38m平均ROC值:%.3f\033[0m' % (pd.Series(rou_ls).mean()))
152     plt.plot(lsr,label='决策树多次计算结果',marker='*')
153     plt.legend(loc='best',fontsize=15)
154     plt.tick_params(labelsize=15)
155     plt.xticks([j for j in range(len(rdls))],[str(j) for j in rdls])
156     plt.xlabel('随机种子数(%s次计算)'%len(rdls),fontsize=18)
157     plt.ylabel('准确率(%)',fontsize=18)
158     plt.show()
159 
160 rand_ls = np.random.randint(0,1000,20)
161 makefigure(rand_ls,X,Y,model,dis_name)###调用函数

  一次随机建模结果

  由ROC图我们发现,模型的敏感性和特异性还是蛮均衡的,整体来看,模型性能总体还是良好的。

  多次平均建模结果

   以上就是模型的综合性能,从平均f1值和ROC值发现,我们的模型鲁棒性和准确性还是蛮优良的,有一定的泛化能力,这得力于开始的数据清洗阶段处理的科学有效

4.数据可视化

(1)数据的特征工程与可视化

  特征工程是机器学习,甚至是深度学习中最为重要的一部分特征工程主要是对特征进行筛选,构造与降维等等,可以选择主要特征和构造新的特征,从而增加模型泛化能力。

  可视化更是让我们清楚了解数据组成部分,为深度分析做准备。

(2) 计算体重、教育年限、工作时长的相关特征值

1 data = pd.read_excel('处理好的数据.xlsx',index_col=0)
2 
3 newdf1 = data[['fnlwgt','education-num','hours-per-week']].dropna()
4 print(newdf1.describe())
5 print(newdf1.corr())

  以上就是相关数据的描述性统计特征值,由此我们发现,这些数据的分布范围和数量级都是不同的,尤其体重的数量级是非常大的,所以在后面的建模中,我们要主要有些变量的取值不同带来的负面效果。

(3)计算体重、教育年限、工作时长它们之间的皮尔森相关性

  为了减少共线性变量带来的运算资源的浪费,接下来,通过变量之间的相关性分析来筛选变量,根据相关系数理论,当两变量之间的相关系数绝对值大于0.8时,可以认为两变量相关性非常强烈,取之一即可,具体见下表展示:

1  sns.heatmap(newdf1.corr(),square = True,  vmax=0.8)
2 plt.show()

  由于上述三种数据本身就是连续型数值数据,所以我们选择这些数据做特征分析和相关性分析,由上述相关系数值的计算,发现这三则的两两之间,并没有什么太大关系,甚至还有点负相关关系。

(4)变量分布的可视化

  绘制概率密度图

 1 ##循环绘制概率密度图
 2 for i in ['fnlwgt','education-num','hours-per-week']:
 3     plt.figure(figsize=(15, 8))
 4     lstemp = data[i]
 5     sns.distplot(lstemp, rug=False, hist=True, bins=15)
 6     plt.tick_params(labelsize=18)
 7     plt.ylabel('概率密度', fontsize=18)
 8     plt.xlabel(i, fontsize=18)
 9     plt.title('%s的概率密度分布图'%i,fontsize=20)
10     plt.show()
11 plt.show()

  以上3幅图就是这三个变量对应的概率密度分布图,我们发现,这些变量的分布并不是很标准的正态分布,但也都有非常突出的区间段数据,尤其是教育年限达到13年左右,也是个人数非常集中的区间段落。每周工作时长集中在40小时左右,看来非常符合8小时工作日的平常制度。

(5)人种分布饼图

 1 # 生成数据
 2 datat = pd.read_excel(path + 'income.xlsx',index_col=0)
 3 datat = list(datat['race'])
 4 set_ls = set(datat)
 5 count_ls = []
 6 for i in set_ls:
 7     count_ls.append(round(datat.count(i) / len(datat),2))
 8 labels = list(set_ls)
 9 share = count_ls
10 
11 # 设置分裂属性
12 explode = [0 for i in range(len(set_ls))]
13 
14 # 分裂饼图
15 plt.figure(figsize=(15, 8))
16 plt.pie(share, explode = explode,
17         labels = labels, autopct = '%3.1f%%',
18         startangle = 180, shadow = True,)
19 plt.tick_params(labelsize=20)
20 # 标题
21 plt.title('人种分布扇形图',fontsize=20)
22 plt.show()

  由上图的扇形图发现,此数据集的人种分布很明显是白人和黑人组成,占了95%以上,这是比较符合美国国情的。

(6)性别与教育年限关联图

 1 def makefigure(xname,yname):
 2 
 3     plt.figure(figsize=(15, 8))
 4     sns.countplot(x=xname,hue=yname, data=data)
 5     plt.legend(fontsize=18)
 6     plt.ylabel(yname,fontsize=18)
 7     plt.xlabel(xname,fontsize=18)
 8     plt.title('%s与%s关联的柱状图'%(xname,yname),fontsize=20)
 9     plt.xticks((0,1),('male','female'))
10     plt.tick_params(labelsize=15)
11     plt.show()
12 
13 makefigure('sex','education-num')
14 makefigure('sex','income')

  由上述分布柱状图我们发现男性和女性的教育年限基本都分布在9-13年这区域,这点是相同的,但不同的是男性的教育年限在第9年的人数比例是非常大的,比女性要大很多。

(7)性别与收入关联图

  我发现在大于50K的人数分布比例上,男性是明显大于女性的(女性比值大约是8.1,男性大约是2.3),这侧面说明高收入人群还是男性居多,男性更多是创造社会财富,女性也许更多的是照顾家庭。

5.完整代码附上

  1 from sklearn.metrics import roc_curve, auc,confusion_matrix,f1_score, precision_score, recall_score
  2 from sklearn.linear_model import LogisticRegression as LR
  3 from sklearn.model_selection import train_test_split
  4 import matplotlib.pyplot as plt
  5 import pandas as pd
  6 import numpy as np
  7 import warnings
  8 import seaborn as sns
  9 import time
 10 
 11 warnings.filterwarnings('ignore')
 12 
 13 start_time = time.time()
 14 plt.rcParams['font.sans-serif']=['SimHei']##中文乱码问题!
 15 plt.rcParams['axes.unicode_minus']=False#横坐标负号显示问题!
 16 
 17 
 18 data = pd.read_excel('income.xlsx',index_col=0)
 19 # print(data)
 20 
 21 colstr = ['workclass','education','marital-status','occupation','relationship','race','sex',
 22           'native-country','income']
 23 
 24 def transform_type(data,col):##转换数据类型
 25 
 26     print('original:',data.shape)
 27     data = data.dropna()
 28     print('now:',data.shape)
 29 
 30     for i in col:
 31         datatemp = data[i]
 32         msg = set(datatemp)
 33         for j,k in zip(msg,[l for l in range(1,len(msg) + 1)]):
 34             data[i][data[i]==j] = k
 35     return data
 36 res = transform_type(data,colstr)
 37 
 38 res.index = [i for i in range(res.shape[0])]
 39 index_ls = res.index
 40 print(res)
 41 
 42 
 43 def substitute_outliner(data,original_ls,yl,tit,mul1,mul2,num_ls):
 44 
 45     print('\033[1;34m{0:*^80}\033[1;0m'.format('特征数据“%s”异常值处理'%yl))
 46     copydata = original_ls.copy()
 47     for i in data[5]:##获取异常值位置
 48         del original_ls[i]##按照位置删除最最保险
 49         upvalue = data[2][i]
 50         downvalue = data[3][i]
 51         originalvalue = copydata[i]
 52         if originalvalue <= downvalue:
 53             changevaluetemp = downvalue * 0.5 + upvalue * 0.25
 54             if changevaluetemp >= upvalue:
 55                 changevalue = upvalue
 56             else:
 57                 changevalue = max(changevaluetemp,downvalue)##最小不低于downvalue,防止upvalue过小
 58             original_ls.insert(i,round(changevalue,1))
 59             print('\033[1;31m异常数据编号为(原始值%s):%s,替换的修正值为:%s,downvalue:%s\033[0m' % (originalvalue, num_ls[i], round(changevalue,2),round(downvalue,2)))
 60         if originalvalue >= upvalue:
 61             changevaluetemp = upvalue * 0.5 + downvalue * 0.25
 62             if changevaluetemp <= downvalue:
 63                 changevalue = downvalue
 64             else:
 65                 changevalue = min(changevaluetemp,upvalue)##最大不超过upvalue,防止downvalue过大
 66             original_ls.insert(i,round(changevalue,1))
 67             print('\033[1;31m异常数据编号为(原始值%s):%s,替换的修正值为:%s,upvalue:%s\033[0m'%(originalvalue,num_ls[i],round(changevalue,2),round(upvalue,2)))
 68 
 69     plt.figure(figsize=(15, 8))
 70     plt.plot(list(copydata), 'y', label='原始数值')
 71     plt.plot(data[1], 'r', label='拟合曲线')
 72     plt.plot(data[2], 'purple', label='拟合上限(%ssigm)曲线'%mul1)
 73     plt.plot(data[3], 'b', label='拟合下限(%ssigm)曲线'%mul2)
 74     plt.plot(original_ls, 'g', label='处理完后的数据')
 75     plt.legend(fontsize=15)
 76     plt.tick_params(labelsize=15)
 77     plt.xlabel('编号',fontsize=18)
 78     plt.ylabel(yl,fontsize=18)
 79     plt.title(tit,fontsize=20)
 80     plt.show()
 81     return original_ls
 82 
 83 def check_outlier(value,mul1,mul2,yl):
 84 
 85     print('\033[1;34m{0:*^80}\033[1;0m'.format('特征数据“%s”预处理'%yl))
 86     x = [j for j in range(len(value))]
 87     coeffs = np.polyfit(x, value, 10)  ##专门求多项式估计参数的函数,根据实际数据波动取相应的阶数
 88     p = np.poly1d(coeffs)  # 一元估计参数
 89     sigm = p(x).std()
 90     sigm_up = p(x) + mul1 * sigm
 91     sigm_down = p(x) - mul2 * sigm
 92     outliner = value[(value < sigm_down) | (value > sigm_up)]#条件筛选
 93     print('\033[1;31m原数据长度:%s,异常数据:%s\033[0m'%(len(value),len(outliner)))
 94     print(outliner)
 95     return list(outliner),p(x),sigm_up,sigm_down,x,list(outliner.index)
 96 
 97 col = list(res)
 98 remove_ls = colstr + ['age','education-num']
 99 
100 for i in remove_ls:
101     col.remove(i)##类别数据不作处理
102 for i in col:##性别和编号不做计算
103     mul1 = 500
104     mul2 = 500##由于数据很大是人为的,这里mul1和mul2参数慎改
105     res1 = check_outlier(res[i],mul1,mul2,i)
106     res2 = substitute_outliner(res1,list(res[i]),i,'“%s”数据预处理图'%i,mul1,mul2,index_ls)
107     res[i] = res2##数据替换
108 
109 del res['capital-gain']
110 del res['capital-loss']
111 del res['education']
112 res.to_excel('处理好的数据.xlsx')
113 
114 
115 data = pd.read_excel('处理好的数据.xlsx',index_col=0)
116 
117 newdf1 = data[['fnlwgt','education-num','hours-per-week']].dropna()
118 print(newdf1.describe())
119 print(newdf1.corr())
120 
121 sns.heatmap(newdf1.corr(),square = True,  vmax=0.8)
122 plt.show()
123 
124 ##循环绘制概率密度图
125 for i in ['fnlwgt','education-num','hours-per-week']:
126     plt.figure(figsize=(15, 8))
127     lstemp = data[i]
128     sns.distplot(lstemp, rug=False, hist=True, bins=15)
129     plt.tick_params(labelsize=18)
130     plt.ylabel('概率密度', fontsize=18)
131     plt.xlabel(i, fontsize=18)
132     plt.title('%s的概率密度分布图'%i,fontsize=20)
133     plt.show()
134 plt.show()
135 
136 # 生成数据
137 datat = pd.read_excel(path + 'income.xlsx',index_col=0)
138 datat = list(datat['race'])
139 set_ls = set(datat)
140 count_ls = []
141 for i in set_ls:
142     count_ls.append(round(datat.count(i) / len(datat),2))
143 labels = list(set_ls)
144 share = count_ls
145 
146 # 设置分裂属性
147 explode = [0 for i in range(len(set_ls))]
148 
149 # 分裂饼图
150 plt.figure(figsize=(15, 8))
151 plt.pie(share, explode = explode,
152         labels = labels, autopct = '%3.1f%%',
153         startangle = 180, shadow = True,)
154 plt.tick_params(labelsize=20)
155 # 标题
156 plt.title('人种分布扇形图',fontsize=20)
157 plt.show()
158 
159 def makefigure(xname,yname):
160 
161     plt.figure(figsize=(15, 8))
162     sns.countplot(x=xname,hue=yname, data=data)
163     plt.legend(fontsize=18)
164     plt.ylabel(yname,fontsize=18)
165     plt.xlabel(xname,fontsize=18)
166     plt.title('%s与%s关联的柱状图'%(xname,yname),fontsize=20)
167     plt.xticks((0,1),('male','female'))
168     plt.tick_params(labelsize=15)
169     plt.show()
170 
171 makefigure('sex','education-num')
172 makefigure('sex','income')
173 
174 data = pd.read_excel('处理好的数据.xlsx',index_col=0)
175 print(data)
176 
177 
178 # del data['fnlwgt']##去除“体重”变量
179 data.iloc[:,1:data.shape[1]-1] = (data.iloc[:,1:data.shape[1]-1] - data.iloc[:,1:data.shape[1]-1].min()) \
180                                  / (data.iloc[:,1:data.shape[1]-1].max() - data.iloc[:,1:data.shape[1]-1].min())
181 X = np.array(data.iloc[:,1:data.shape[1]-1])##自变量的读取
182 
183 Y = np.array(data.iloc[:,data.shape[1]-1])##因变量的读取
184 dis_name = [1,2]
185 rd = 211
186 
187 
188 ##绘制roc图
189 def make_figure_auc_roc(true_label,score,class_):
190     plt.figure(figsize=(15, 8))
191 
192     fpr, tpr, thresholds = roc_curve(true_label,score,pos_label=class_,drop_intermediate=False)
193     ###返回的是一系列thresholds阈值
194     roc_auc = auc(fpr, tpr)
195     roc_result = pd.DataFrame({'fpr' : fpr,'tpr' : tpr, 'tf' : tpr - (1-fpr),'thresholds' : thresholds})
196 #     roc_result.iloc[(roc_result.tf-0).abs().argsort()[:1]]
197     optimal_idx = np.argmax(tpr - fpr)
198     optimal_threshold = thresholds[optimal_idx]
199     y = tpr[optimal_idx]
200     x = fpr[optimal_idx]
201     plt.figure(figsize=(8,5))
202     plt.plot(fpr, tpr, color='navy',label='AUC=%.3f' % roc_auc)
203     plt.plot([-0.005, 1.005], [-0.005, 1.005], color='orange',linestyle='--')
204     plt.xlabel('1-特异度',fontsize=10)
205     plt.ylabel('敏感度',fontsize=10)
206     plt.scatter(x, y, c='red',s=15)
207     plt.tick_params(labelsize=12,rotation=10)
208     plt.title('ROC曲线',fontsize=12)
209     plt.legend(loc='best',fontsize=18)
210     plt.text(x+0.05,y-0.05,s='('+str(round(1-x, 3))+', '+str(round(y, 3))+')',fontsize=15)
211     plt.show()
212     return roc_auc
213 
214 def cm_plot(yp, y):##混淆矩阵
215     plt.figure(figsize=(15, 8))
216     cm = confusion_matrix(yp, y)  # 混淆矩阵
217     plt.matshow(cm, cmap=plt.cm.Greens)  # 画混淆矩阵图,配色风格使用cm.Greens,更多风格请参考官网。
218     plt.colorbar()  # 颜色标签
219 
220     for x in range(len(cm)):  # 数据标签
221         for y in range(len(cm)):
222             plt.annotate(cm[x, y], xy=(x, y), horizontalalignment='center', verticalalignment='center')
223     plt.ylabel('真实标签',fontsize=10)  # 坐标轴标签
224     plt.xlabel('预测标签',fontsize=10)  # 坐标轴标签
225     plt.title('预测混淆矩阵图', fontsize=12)
226     plt.show()
227 
228 ##自定义准确率计算
229 def show_result(dis_name, pre_ls, real_ls,rd):##准确率
230 
231     ls_r = []
232     ls_c = []
233     for d in dis_name:
234         res_ls = []
235         for i, j in zip(pre_ls, list(real_ls)):
236             if i == j == d:
237                 res_ls.append('正确')
238 
239         ls_r.append(len(res_ls) / list(real_ls).count(d))
240         ls_c.append((len(res_ls),list(real_ls).count(d)))
241 
242         print('\033[1;32m随机种子是%s时,%s(%s/%s)准确率:%.3f%%\033[0m' % (rd,d, len(res_ls), list(real_ls).count(d), len(res_ls) / list(real_ls).count(d) * 100))
243 
244     res_ls = []
245     for i, j in zip(pre_ls, list(real_ls)):
246         if i == j:
247             res_ls.append('正确')
248         else:
249             res_ls.append('错误')
250 
251     print('\033[1;31m随机种子是%s时,总预测(%s/%s)准确率:%.3f%%\033[0m' % (rd,res_ls.count('正确'), len(res_ls), res_ls.count('正确') / len(res_ls) * 100))
252     df = pd.DataFrame([list(real_ls), pre_ls, res_ls], index=['真实', '预测', '预测结果']).T
253     allcorretrate = res_ls.count('正确') / len(res_ls) * 100
254     return df,allcorretrate
255 
256 
257 ##建立LR模型
258 def model(x,y,rd=rd):
259 
260     xtrain, xtest, ytrain, ytest = train_test_split(x, y, test_size=0.3, random_state=rd)
261     lr = LR(solver='liblinear')  # 建立逻辑回归模型
262     lr.fit(xtrain, ytrain)  # 用特征数据来训练模型
263     pre_lr = lr.predict(xtest)
264     pro_lr = lr.predict_proba(xtest)
265 
266     return pre_lr,ytest,pro_lr,lr.classes_[0]
267 
268 print('\033[1;38m{0:*^80}\033[0m'.format('一次实验随机种子为%s的准确率汇总'%rd))
269 
270 res = model(X,Y)
271 make_figure_auc_roc(res[1], res[2][:, 0], res[3])
272 cm_plot(res[0],res[1])
273 show_result(dis_name,res[0],res[1],rd)
274 
275 f1 = round(f1_score(res[1], res[0], average='macro'),3)##F计算
276 p = round(precision_score(res[1], res[0], average='macro'),3)##精准率计算
277 r = round(recall_score(res[1], res[0], average='macro'),3)##召回率计算
278 print(f1,p,r)
279 
280 
281 ##循环调用LR模型并可视化结果
282 
283 def makefigure(rdls,x,y,func,dn):
284 
285     plt.figure(figsize=(15, 8))
286     print('\033[1;38m{0:*^80}\033[0m'.format('多次实验的准确率汇总'))
287     lsr = []
288     f1_ls = []
289     p_ls = []
290     r_ls = []
291     rou_ls = []
292     for k in rdls:
293         R = func(x,y,k)##循环调用模型
294         rr = show_result(dn, R[0], R[1],k)
295         f1 = f1_score(R[1], R[0], average='macro')
296         p = precision_score(R[1], R[0], average='macro')
297         r = recall_score(R[1], R[0], average='macro')
298         roc = make_figure_auc_roc(R[1], R[2][:, 0], R[3])
299         f1_ls.append(f1)
300         p_ls.append(p)
301         r_ls.append(r)
302         lsr.append(rr[1])
303         rou_ls.append(roc)
304     plt.figure(figsize=(15, 8))
305     print('\033[1;38m平均准确率:%.3f%%\033[0m'%(pd.Series(lsr).mean()))
306     print('\033[1;38m平均f1值:%.3f\033[0m' % (pd.Series(f1_ls).mean()))
307     print('\033[1;38m平均召回率值:%.3f\033[0m' % (pd.Series(p_ls).mean()))
308     print('\033[1;38m平均精准率值:%.3f\033[0m' % (pd.Series(r_ls).mean()))
309     print('\033[1;38m平均ROC值:%.3f\033[0m' % (pd.Series(rou_ls).mean()))
310     plt.plot(lsr,label='决策树多次计算结果',marker='*')
311     plt.legend(loc='best',fontsize=15)
312     plt.tick_params(labelsize=15)
313     plt.xticks([j for j in range(len(rdls))],[str(j) for j in rdls])
314     plt.xlabel('随机种子数(%s次计算)'%len(rdls),fontsize=18)
315     plt.ylabel('准确率(%)',fontsize=18)
316     plt.show()
317 
318 rand_ls = np.random.randint(0,1000,20)
319 makefigure(rand_ls,X,Y,model,dis_name)###调用函数

四、总结

  主要先对数据预处理清洗,然后进行一些可视化分析,再然后我们对逻辑回归模型底层逻辑进行了一些回顾,并选择此机器学习模型,实际建模时,我们设置好模型参数,对数据进行建模和分析,最终我们给出模型的综合评价指标,做到客观科学的评价模型。

  通过一系列方法运用,我们客观且科学地建立了基于人群特征数据的人群收入分类器,而且准确率还不错,这很有效地帮助我们解决在实际人群不知道是高收入还是低收入的情况下,通过模型来给出判别结果,在可视化分析阶段,我们也总结了很多人群内在信息的相关特点。

  但是方法是多样的,我们可以建立深度学习模型如LSTM、CNN或者其他机器学习如支持向量机模型SVM、随机森林RF模型等等,我们同时可以对特征进行相关建模,比如更高级的特征筛选或者特征降维,这都是需要努力的方向!

标签:数据分析,plt,##,res,挖掘,ls,薪资,033,data
From: https://www.cnblogs.com/msadew/p/16997312.html

相关文章