ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

天池幸福感挖掘分析与预测

2020-12-26 15:00:40  阅读:218  来源: 互联网

标签:status full get 幸福感 DataFrame replace pd 挖掘 天池


数据链接

  1. 我们先导入数据以及一些会用到的包
#导入数据包
import pandas as pd
import numpy as np
#调整显示范围,显示更多的列
pd.options.display.max_rows = 10
pd.options.display.max_columns = 45
#导入训练数据集
train = pd.read_csv('./happiness_train_abbr.csv')
#导入测试数据集
test = pd.read_csv('./happiness_test_abbr.csv')
#查看数据有多少行,多少列
print(train.shape, test.shape)

# (8000, 42) (2968, 41)

因为数据中存在“-1 = 不适用; -2 = 不知道; -3 = 拒绝回答; -8 = 无法回答”的情况,同时还包含一些空值,所以我们需要对这些值进行预处理,在预处理之前,我们将训练集和测试集合并,一块进行处理。

#合并数据集,方便同时对两个数据集进行清洗
full = train.append(test, ignore_index = True, sort=False)
print (full.shape)

# 下面来看一看每一列的数据类型以及数据总数
full.info()

# (10968, 42)

在这里插入图片描述

可以看到数据类型为:float64(7), int64(34), object(1), 其中family_income缺失一条数据,其中work_status, work_yr, work_type, work_manage这4列的数据缺失严重

下面我们来对上面提到的一些值进行处理。

#列名class为Python保留字,要改名,不然在操作中很可能报错
full.rename(columns={'class': 'Class'}, inplace=True)
#列nationality为-8的值,将其替换为8表示其他。
full['nationality'] = full.nationality.replace(-8, 8)
#列religion和religion_freq为-8的值,将其替换为最频繁出现的值1。
full['religion'] = full.religion.replace(-8, 1)
full['religion_freq'] = full.religion_freq.replace(-8, 1)
#列religion和religion_freq为-8的值,将其替换为最频繁出现的值1。
full['religion'] = full.religion.replace(-8, 1)
full['religion_freq'] = full.religion_freq.replace(-8, 1)
#将income列为-1,-2,-3的值,先替换为空值,再用平均值替换
full['income'] = full.income.replace([-1, -2, -3], np.nan)
full['income'] = full.income.replace(np.nan, full['income'].mean())
#列nationality为-8的值,将其替换为最频繁出现的值1。
full['political'] = full.political.replace(-8, 1)
#列health,health_problem为-8的值,将其替换为3,表示一般。
full['health'] = full.health.replace(-8, 3)
full['health_problem'] = full.health_problem.replace(-8, 3)
#列depression为-8的值,将其替换为3,表示一般。
full['depression'] = full.depression.replace(-8, 3)
#列socialize,relax,learn为-8的值,将其替换为3,表示有时。
full['socialize'] = full.socialize.replace(-8, 3)
full['relax'] = full.relax.replace(-8, 3)
full['learn'] = full.learn.replace(-8, 3)
#列equity为-8的值,将其替换为3,表示中间态度。
full['equity'] = full.equity.replace(-8, 3)
#列class为-8的值,将其替换为最频繁出现的5。
full['Class'] = full.Class.replace(-8, 5)
#将family_income列为-1,-2,-3的值,先替换为空值,再用平均值替换
full['family_income'] = full.family_income.replace([-1, -2, -3], np.nan)
full['family_income'] = full.family_income.replace(np.nan, full['family_income'].mean())
#将family_m列为-1,-2,-3的值,替换为1
full['family_m'] = full.family_m.replace([-1, -2, -3], 1)
#列family_status为-8的值,将其替换为3,表示平均水平
full['family_status'] = full.family_status.replace(-8, 3)
#将house列为-1,-2,-3的值,替换为0
full['house'] = full.house.replace([-1, -2, -3], 0)
#将car列为-8的值,替换为最频繁出现的2
full['car'] = full.car.replace(-8, 2)
#将status_peer,status_3_before,view列为-8的值,替换为差不多(一般)
full['status_peer'] = full.status_peer.replace(-8, 2)
full['status_3_before'] = full.status_3_before.replace(-8, 2)
full['view'] = full.view.replace(-8, 3)
#inc_ability缺失值过多,将inc_ability列为-8的值,替换为0
full['inc_ability'] = full.inc_ability.replace(-8, 0)
#将happiness列为-8的值,替换为3 "说不上幸福不幸福"
full['happiness'] = full.happiness.replace(-8, 3)

时间格式处理

#survey_time转换成时间格式的数据
full['survey_datetime'] = pd.to_datetime(
    full.survey_time,
    format='%Y/%m/%d %H:%M')
#计算受访者的年龄,所有问卷都是2015年填写的,所以 2015-birth 就是年龄
full['age'] = 2015 - full['birth']

体重数据处理,将体重换为国际通用的BMI指数

#计算BMI指数,注意数据集中的身高单位是cm,体重的单位是斤(500g)
# BMI计算公式:体重(kg)/身高(m)的平方
full['bmi'] = (full['weight_jin'] /2) / (full['height_cm'] / 100) ** 2

对于分类数据,用One-hot编码,产生虚拟变量(dummy variables),都用0-1表示。

#survey_type分为2类,0=农村,1=城市
full['survey_type'] = full.survey_type.replace(2, 0)
#gender分为2类,0=女,1=男
full['gender'] = full.gender.replace(2, 0)
#民族nationality
nationalityDf = pd.DataFrame()
#使用get_dummies进行one-hot编码,列名前缀是nationality
nationalityDf = pd.get_dummies( full['nationality'] , prefix='nationality' )
# nationality总共有八种选择,所以用one-hot编码之后,每一条数据就是一个8维的向量
nationalityDf.head(5)   

在这里插入图片描述

#参与宗教活动频繁程度religion_freq
religion_freqDf = pd.DataFrame()
#使用get_dummies进行one-hot编码,列名前缀是religion_freq
religion_freqDf = pd.get_dummies( full['religion_freq'] , prefix='religion_freq' )
# 同上,religion_freq有9个选项
# 1 = 没有受过任何教育; 2 = 私塾、扫盲班; 3 = 小学; 4 = 初中; 5 = 职业高中; 6 = 普通高中; 7 = 中专; 8 = 技校; 9 = 大学专科(成人高等教育); 10 = 大学专科(正规高等教育); 11 = 大学本科(成人高等教育); 12 = 大学本科(正规高等教育); 13 = 研究生及以上; 14 = 其他; 
religion_freqDf.head(5)

在这里插入图片描述
edu的选项比较多,有14种,要对其分组后再做比较。
分如下成几组
1.小学及其他,包括原数据中的1,2,3,14
2.初中,对应原数据中的4
3.高中,对应原数据中的5,6,7,8
4.大学,对应原数据中的9,10,11,12
5.研究生,对应原数据中的13

#对教育程度分组,将分组结果放在edu_group字段
bins = [0, 3, 4, 8, 12, 13, 14]
eduLabels = [1, 2, 3, 4, 5, 6]
full['edu_group'] = pd.cut(
    full.edu,
    bins,
    labels=eduLabels)
#分类的标签不能重复,edu_group值为6的换乘1
full['edu_group'] = full.edu_group.replace(6, 1)
#受教育层次edu_group
edu_groupDf = pd.DataFrame()
#使用get_dummies进行one-hot编码,列名前缀是edu_group
edu_groupDf = pd.get_dummies( full['edu_group'] , prefix='edu_group' )
#political政治面貌
politicalDf = pd.DataFrame()
politicalDf = pd.get_dummies( full['political'] , prefix='political' )
#health健康状况
healthDf = pd.DataFrame()
healthDf = pd.get_dummies( full['health'] , prefix='health' )
#health_problem健康问题的影响
health_problemDf = pd.DataFrame()
health_problemDf = pd.get_dummies( full['health_problem'] , prefix='health_problem' )
#depression心情抑郁
depressionDf = pd.DataFrame()
depressionDf = pd.get_dummies( full['depression'] , prefix='depression' )
#hukou户口
hukouDf = pd.DataFrame()
hukouDf = pd.get_dummies( full['hukou'] , prefix='hukou' )
#socialize社交
socializeDf = pd.DataFrame()
socializeDf = pd.get_dummies( full['socialize'] , prefix='socialize' )
#relax放松
relaxDf = pd.DataFrame()
relaxDf = pd.get_dummies( full['relax'] , prefix='relax' )
#learn学习
learnDf = pd.DataFrame()
learnDf = pd.get_dummies( full['learn'] , prefix='learn' )
#equity公平
equityDf = pd.DataFrame()
equityDf = pd.get_dummies( full['equity'] , prefix='equity' )
#Class等级
ClassDf = pd.DataFrame()
ClassDf = pd.get_dummies( full['Class'] , prefix='Class' )
#work_exper工作经历
work_experDf = pd.DataFrame()
work_experDf = pd.get_dummies( full['work_exper'] , prefix='work_exper' )
#family_status家庭经济状况
family_statusDf = pd.DataFrame()
family_statusDf = pd.get_dummies( full['family_status'] , prefix='family_status' )
#car是否拥有小汽车,转变成0=没有,1=有
full['car'] = full.car.replace(2, 0)
#marital婚姻状况
maritalDf = pd.DataFrame()
maritalDf = pd.get_dummies( full['marital'] , prefix='marital' )
#status_peer经济社会地位
status_peerDf = pd.DataFrame()
status_peerDf = pd.get_dummies( full['status_peer'] , prefix='status_peer' )
#status_3_before,3年来社会经济地位的变化
status_3_beforeDf = pd.DataFrame()
status_3_beforeDf = pd.get_dummies( full['status_3_before'] , prefix='status_3_before' )
#view观点
viewDf = pd.DataFrame()
viewDf = pd.get_dummies( full['view'] , prefix='view' )
#inc_ability收入合理性
inc_abilityDf = pd.DataFrame()
inc_abilityDf = pd.get_dummies( full['inc_ability'] , prefix='inc_ability' )
#删除空值的列
inc_abilityDf.drop('inc_ability_0',axis=1,inplace=True)

按年龄分析:研究不同年龄的幸福感情况。首先对样本的年龄进行分类,分成5个年龄段。
按照20%, 40%, 60%, 80%百分位数设置阈值,这样使每个组的样本数大致相等。

full.age.describe(percentiles=[0.2, 0.4, 0.6, 0.8])

在这里插入图片描述
分成5个年龄段,分别为[18, 33], [34, 45], [46, 54], [55, 65], [66, 95]

#对年龄分组,将分组结果放在age_group字段
bins = [17, 33, 45, 54, 65, 100]
ageLabels = ['33岁及以下', '34-45岁', '46-54岁', '55-65岁', '66岁及以上']
full['age_group'] = pd.cut(
    full.age,
    bins,
    labels=ageLabels)
#查看各年龄层次幸福感的平均情况
age_mean = full.groupby(
    by=['age_group']
)['happiness'].agg('mean')
age_mean

在这里插入图片描述

进行特征选择

#设置一个新的DataFrame,在新的DataFrame上添加虚拟变量以替代原来的变量
nfull= full
#添加虚拟变量,然后删除原来的变量
nfull = pd.concat([full, nationalityDf, religion_freqDf, edu_groupDf,
                   politicalDf, healthDf, health_problemDf, depressionDf,
                   hukouDf, socializeDf, relaxDf, learnDf, equityDf,
                   ClassDf, work_experDf, family_statusDf, maritalDf,
                   status_peerDf, status_3_beforeDf, viewDf,
                   inc_abilityDf],axis=1)
#work_exper, work_status, work_yr, work_type这几个变量缺失的数据太多,将其删除
nfull.drop(['nationality', 'religion_freq', 'edu', 'edu_group', 'political',
            'health', 'health_problem', 'depression', 'hukou', 'socialize',
            'relax', 'learn', 'equity', 'Class', 'work_exper', 			
            'family_status', 'marital', 'status_peer', 'status_3_before',
            'view', 'inc_ability', 'weight_jin', 'work_exper',
            'work_status','work_yr', 'work_type',
            'age_group'],axis=1,inplace=True)
nfull.head(5)

在这里插入图片描述
查看各个特征之间的相关性

#相关性矩阵
corrDf = nfull.corr() 
corrDf

在这里插入图片描述

#查看各个特征与幸福感(happiness)的相关系数,ascending=False表示按降序排列
pd.options.display.max_rows = 20
corrDf['happiness'].sort_values(ascending =False)

在这里插入图片描述
特征选择

#特征选择
full_X = pd.concat([status_peerDf,
                    family_statusDf,
                    equityDf,
                    depressionDf,
                    ClassDf] , axis=1 )
full_X.head(5)

在这里插入图片描述
数据划分

#训练数据集有8000行
sourceRow=8000
#从特征集合full_X中提取原始数据集,提取前8000行数据时
#原始数据集:特征
source_X = full_X.loc[0:sourceRow-1, :]
#原始数据集:标签
source_y = nfull.loc[0:sourceRow-1, 'happiness']
#预测数据集:特征
pred_X = full_X.loc[sourceRow:,:]
#查看两个数据集有多少行
print('原始数据集有多少行:',source_X.shape[0])
print('预测数据集有多少行:',pred_X.shape[0])

from sklearn.model_selection import  train_test_split
#用train_test_split函数,从样本中随机的按比例选取train data和test data
#建立模型用的训练数据集和测试数据集
train_X, test_X, train_y, test_y = train_test_split(source_X ,
                                                    source_y,
                                                    train_size=.8)
#输出数据集大小
print ('原始数据集特征:',source_X.shape, 
       '训练数据集特征:',train_X.shape ,
      '测试数据集特征:',test_X.shape)

print ('原始数据集标签:',source_y.shape, 
       '训练数据集标签:',train_y.shape ,
      '测试数据集标签:',test_y.shape)
# 原始数据集有多少行: 8000
# 预测数据集有多少行: 2968
# 原始数据集特征: (8000, 28) 训练数据集特征: (6400, 28) 测试数据集特征: (1600, 28)
# 原始数据集标签: (8000,) 训练数据集标签: (6400,) 测试数据集标签: (1600,)

下面我们就调用相关算法进行预测

先是调用knn,并设置不同的n值进行验证;

#第1步:导入算法
from sklearn.neighbors import KNeighborsRegressor
#第2步:创建模型:逻辑回归(logistic regression)
for i in range(1,1000):
    model = KNeighborsRegressor(n_neighbors=i, p=2, metric="minkowski")
#第3步:训练模型
    model.fit( train_X , train_y )
    print(i, model.score(test_X , test_y ))

然后再简单的使用贝叶斯模型进行验证

#查看模型的正确率
from sklearn.naive_bayes import GaussianNB
# 使用高斯朴素贝叶斯进行计算
clf = GaussianNB(var_smoothing=1e-8)
clf.fit(train_X , train_y)
print(model.score(test_X , test_y ))

# 0.23487439269921995

然后再用逻辑回归进行验证

#第1步:导入算法
from sklearn.linear_model import LogisticRegression
#第2步:创建模型:逻辑回归(logistic regression)
model = LogisticRegression()
#第3步:训练模型
model.fit( train_X , train_y )
#查看模型的正确率
model.score(test_X , test_y )

# 0.639375

三种算法中,只有逻辑回归效果稍好一点,所以下面用逻辑回归来做测试

#运用模型,对幸福感进行预测
pred_Y = model.predict(pred_X)
#生成的结果是浮点型数据
pred_Y

# array([4., 3., 4., ..., 4., 4., 5.])
#题目要求上传的结果要为整数型,所以要进行转换
pred_Y=pred_Y.astype(int)
#受访者id
id = full.loc[sourceRow:,'id']
#把预测结果放到数据框中:列名id是受访者编号,列名happiness预测的幸福感
predDf = pd.DataFrame( 
    { 'id': id , 
     'happiness': pred_Y } )
predDf.head()

在这里插入图片描述

#将结果保存为csv文件,最后将这个文件上传至阿里云天池,提交结果
predDf.to_csv( './happiness_pred.csv' , index = False )

参考链接

标签:status,full,get,幸福感,DataFrame,replace,pd,挖掘,天池
来源: https://blog.csdn.net/qq_45435247/article/details/111739018

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有