大五类人格特征分析
1.数据介绍
1.1 数据背景
麻省理工的心理学教授倾向通过TheBigFive(大五类人格特征)来描述人的人格与个性。 大五类因素包括:严谨性、外向性、开放性、宜人性与神经质人格特质。
一般记忆为 OCEAN-海洋或NEOAC-独木舟):
- O 代表 Openness to experience (开放性)
- C 代表 Conscientiousness(严谨性)
- E 代表 Extraversion(外向性)
- A 代表 Agreeableness (宜人性)
- N 代表 Neuroticism(神经质)
本数据集包含了由Open Psychometrics在线收集的1,015,342份问卷的答案。
1.2 数据说明
这些数据是通过互动式在线性格测试收集的(2016-2018)。
该人格测试是用IPIP的 "大五因子标记 "构建的。https://ipip.ori.org/newBigFive5broadKey.htm
在测试开始时,参与者被告知他们的回答将被记录并用于研究,并在测试结束时被要求确认他们的同意。
以下项目被放在一页上,每个项目都用单选按钮进行五分制评分。
页面上的顺序是:EXT1、AGR1、CSN1、EST1、OPN1、EXT2等等。
评分标准是:1=不同意,3=中立,5=同意。
EXT - Extraversion - 外向性,指个体对外部世界的积极投入程度。
EST - Neuroticism - 神经质,指个体体验消极情绪的倾向。
AGR - Agreeableness - 宜人性,指个体在合作与社会和谐性方面的差异。
CSN - Conscientiousness - 严谨性,指个体在目标导向行为上的组织、坚持和动机。
OPN - Openness to experience - 开放性,指个体对经验持开放、探求的态度。
单选项目字段 | 题目描述 |
---|---|
EXT1 | 我是聚会的主角。 |
EXT2 | 我不常说话。 |
EXT3 | 我觉得与人相处很舒服。 |
EXT4 | 我保持在后台。 |
EXT5 | 我开始谈话。 |
EXT6 | 我没有什么可说的。 |
EXT7 | 我在聚会上与很多不同的人交谈。 |
EXT8 | 我不喜欢引起别人的注意。 |
EXT9 | 我不介意成为注意力的中心。 |
EXT10 | 我在陌生人面前很安静。 |
EST1 | 我很容易产生压力。 |
EST2 | 我大部分时间都很放松。 |
EST3 | 我担心的事情。 |
EST4 | 我很少感到忧郁。 |
EST5 | 我很容易被打擾。 |
EST6 | 我很容易感到不安。 |
EST7 | 我经常改变我的情绪。 |
EST8 | 我经常有情绪波动。 |
EST9 | 我很容易被激怒. |
EST10 | 我经常感到忧郁。 |
AGR1 | 我对别人的关心很少。 |
AGR2 | 我对人感兴趣。 |
AGR3 | 我羞辱别人。 |
AGR4 | 我同情别人的感受。 |
AGR5 | 我对别人的问题不感兴趣。 |
AGR6 | 我有一颗柔软的心。 |
AGR7 | 我对别人不感兴趣。 |
AGR8 | 我为他人抽出时间。 |
AGR9 | 我感受别人的情绪。 |
AGR10 | 我让人感到安心。 |
CSN1 | 我总是做好准备。 |
CSN2 | 我把我的物品留在身边。 |
CSN3 | 我注意细节。 |
CSN4 | 我把事情搞得一团糟。 |
CSN5 | 我立马完成家务事。 |
CSN6 | 我经常忘记把东西放回原处。 |
CSN7 | 我喜欢秩序。 |
CSN8 | 我推卸责任。 |
CSN9 | 我遵守时间表。 |
CSN10 | 我在工作中很严谨。 |
OPN1 | 我有丰富的词汇量。 |
OPN2 | 我很难理解抽象的概念。 |
OPN3 | 我有生动的想象力。 |
OPN4 | 我对抽象的想法不感兴趣。 |
OPN5 | 我有出色的想法。 |
OPN6 | 我没有良好的想象力。 |
OPN7 | 我对事物的理解很快。 |
OPN8 | 我使用困难的词语。 |
OPN9 | 我花时间反思事物。 |
OPN10 | 我充满了想法。 |
在每个问题上花费的时间也以毫秒为单位记录。这些是以_E结尾的变量。这是用点击问题的按钮时的时间减去最近一次点击其他按钮的时间来计算的。
数据字段 | 说明 |
---|---|
dateload | 调查开始的时间戳。 |
screenw | 用户屏幕的宽度,像素 |
screenh | 用户屏幕的高度,单位是像素。 |
introelapse | 在登陆/介绍页面上花费的时间(秒)。 |
testelapse | 在有调查问题的页面上花费的时间(秒)。 |
endelapse | 在最终确定页面上花费的时间,以秒为单位(在这个页面上,用户被要求表明他们是否已经准确回答,他们的答案可以被存储并用于研究。再次强调:本数据集只包括对这个问题回答 "是 "的用户,用户可以自由地回答 "否",并且仍然可以查看他们的结果。) |
IPC | 数据集中来自用户IP地址的记录数量。为了达到最大的清洁度,只使用此值为1的记录。高值可能是因为共享网络(如整个大学)或多次提交的原因 |
country | 国家,由技术信息决定(不作为问题)。 |
lat_appx_lots_of_err | 用户的近似纬度,由技术信息决定,这不是非常准确的。阅读文章 "互联网地图故障如何将堪萨斯州的一个随机农场变成数字地狱" ,了解依赖这一信息的危险性。 |
long_appx_lots_of_err | 用户的近似经度 |
1.3 数据来源
https://www.kaggle.com/datasets/tunguz/big-five-personality-test
2.数据分析
2.1数据载入
import numpy as np
# 导入pandas包
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import os
import warnings
warnings.filterwarnings('ignore')
!unzip -qoa data/data176153/data-final.zip
# 读取五大人格测试数据
data_path="data-final.csv"
data_raw=pd.read_csv(data_path)
data = data_raw.copy()
pd.options.display.max_columns = 150
# 缺失值处理
data.drop(data.columns[50:107], axis=1, inplace=True)
data.drop(data.columns[51:], axis=1, inplace=True)
print('参与者数量: ', len(data))
data.head()
参与者数量: 1015341
2.2 数据基本情况
print('是否缺少任何值? ', data.isnull().values.any())
print('缺少多少值? ', data.isnull().values.sum())
data.dropna(inplace=True)
print('消除缺失值后的参与者数量: ', len(data))
是否缺少任何值? True
缺少多少值? 89227
消除缺失值后的参与者数量: 1013481
2.3 参与者的国籍分布
# 参与者的国籍分布
countries = pd.DataFrame(data['country'].value_counts())
countries_5000 = countries[countries['country'] >= 5000]
plt.figure(figsize=(15,5))
sns.barplot(data=countries_5000, x=countries_5000.index, y='country')
plt.title('参与人数超过5000人的国家')
plt.ylabel('参与者');
2.4 检查问题分布
# 问题和问题分组
ext_questions = {'EXT1' : 'I am the life of the party',
'EXT2' : 'I dont talk a lot',
'EXT3' : 'I feel comfortable around people',
'EXT4' : 'I keep in the background',
'EXT5' : 'I start conversations',
'EXT6' : 'I have little to say',
'EXT7' : 'I talk to a lot of different people at parties',
'EXT8' : 'I dont like to draw attention to myself',
'EXT9' : 'I dont mind being the center of attention',
'EXT10': 'I am quiet around strangers'}
est_questions = {'EST1' : 'I get stressed out easily',
'EST2' : 'I am relaxed most of the time',
'EST3' : 'I worry about things',
'EST4' : 'I seldom feel blue',
'EST5' : 'I am easily disturbed',
'EST6' : 'I get upset easily',
'EST7' : 'I change my mood a lot',
'EST8' : 'I have frequent mood swings',
'EST9' : 'I get irritated easily',
'EST10': 'I often feel blue'}
agr_questions = {'AGR1' : 'I feel little concern for others',
'AGR2' : 'I am interested in people',
'AGR3' : 'I insult people',
'AGR4' : 'I sympathize with others feelings',
'AGR5' : 'I am not interested in other peoples problems',
'AGR6' : 'I have a soft heart',
'AGR7' : 'I am not really interested in others',
'AGR8' : 'I take time out for others',
'AGR9' : 'I feel others emotions',
'AGR10': 'I make people feel at ease'}
csn_questions = {'CSN1' : 'I am always prepared',
'CSN2' : 'I leave my belongings around',
'CSN3' : 'I pay attention to details',
'CSN4' : 'I make a mess of things',
'CSN5' : 'I get chores done right away',
'CSN6' : 'I often forget to put things back in their proper place',
'CSN7' : 'I like order',
'CSN8' : 'I shirk my duties',
'CSN9' : 'I follow a schedule',
'CSN10' : 'I am exacting in my work'}
opn_questions = {'OPN1' : 'I have a rich vocabulary',
'OPN2' : 'I have difficulty understanding abstract ideas',
'OPN3' : 'I have a vivid imagination',
'OPN4' : 'I am not interested in abstract ideas',
'OPN5' : 'I have excellent ideas',
'OPN6' : 'I do not have a good imagination',
'OPN7' : 'I am quick to understand things',
'OPN8' : 'I use difficult words',
'OPN9' : 'I spend time reflecting on things',
'OPN10': 'I am full of ideas'}
# 分组名称和列名
EXT = [column for column in data if column.startswith('EXT')]
EST = [column for column in data if column.startswith('EST')]
AGR = [column for column in data if column.startswith('AGR')]
CSN = [column for column in data if column.startswith('CSN')]
OPN = [column for column in data if column.startswith('OPN')]
# 定义一个函数来可视化问题和答案分布
def vis_questions(groupname, questions, color):
plt.figure(figsize=(40,60))
for i in range(1, 11):
plt.subplot(10,5,i)
plt.hist(data[groupname[i-1]], bins=14, color= color, alpha=.5)
plt.title(questions[groupname[i-1]], fontsize=18)
print('与外向型人格相关的问答')
vis_questions(EXT, ext_questions, 'green')
与外向型人格相关的问答
print('神经质人格相关的问答')
vis_questions(EST, est_questions, 'pink')
神经质人格相关的问答
print('宜人性格相关的问答')
vis_questions(AGR, agr_questions, 'red')
宜人性格相关的问答
print('尽责人格相关的问答')
vis_questions(CSN, csn_questions, 'purple')
尽责人格相关的问答
print('开放人格相关的问答')
vis_questions(OPN, opn_questions, 'blue')
开放人格相关的问答
3.模型训练 & 预测
3.1 聚类可视化分析
# https://www.scikit-yb.org/en/latest/ 可视化神器
# 需要安装后重启notebook
!pip install -q yellowbrick
# 归一化(5000数据)
from sklearn.preprocessing import MinMaxScaler
df = data.drop('country', axis=1)
columns = list(df.columns)
scaler = MinMaxScaler(feature_range=(0,1))
df = scaler.fit_transform(df)
df = pd.DataFrame(df, columns=columns)
df_sample = df[:5000]
# Visualize the elbow
from sklearn.cluster import KMeans
from yellowbrick.cluster import KElbowVisualizer
kmeans = KMeans()
visualizer = KElbowVisualizer(kmeans, k=(2,15))
visualizer.fit(df_sample)
visualizer.poof()
如图所示:5类是比较合适的。
3.2 模型拟合
将参与者分为5个性格组
# 创建 K-means Cluster Model
from sklearn.cluster import KMeans
# 使用未归一化数据
df_model = data.drop('country', axis=1)
# 拟合模型
kmeans = KMeans(n_clusters=5)
k_fit = kmeans.fit(df_model)
# 预测聚类
pd.options.display.max_columns = 10
predictions = k_fit.labels_
df_model['Clusters'] = predictions
df_model.head()
3.3 分析模型和预测
每个cluster有多少个人?
df_model.Clusters.value_counts()
0 227165
2 212974
3 209628
4 200827
1 162887
Name: Clusters, dtype: int64
让我们根据聚类对结果进行分组。这样,我们可以调查每个集群中每个问题的平均答案。
这样,我们就可以直观地了解我们的模型如何对人进行分类。
pd.options.display.max_columns = 150
df_model.groupby('Clusters').mean()
<td>1.966249</td>
<td>4.012560</td>
<td>2.983693</td>
<td>4.262811</td>
<td>3.814954</td>
总结一下每个问题组(EXT,EST…),看看我们是否能看到一个模式。
col_list = list(df_model)
ext = col_list[0:10]
est = col_list[10:20]
agr = col_list[20:30]
csn = col_list[30:40]
opn = col_list[40:50]
data_sums = pd.DataFrame()
data_sums['extroversion'] = df_model[ext].sum(axis=1)/10
data_sums['neurotic'] = df_model[est].sum(axis=1)/10
data_sums['agreeable'] = df_model[agr].sum(axis=1)/10
data_sums['conscientious'] = df_model[csn].sum(axis=1)/10
data_sums['open'] = df_model[opn].sum(axis=1)/10
data_sums['clusters'] = predictions
data_sums.groupby('clusters').mean()
dataclusters = data_sums.groupby('clusters').mean()
plt.figure(figsize=(22,3))
for i in range(0, 5):
plt.subplot(1,5,i+1)
plt.bar(dataclusters.columns, dataclusters.iloc[:, i], color='green', alpha=0.2)
plt.plot(dataclusters.columns, dataclusters.iloc[:, i], color='red')
plt.title('Cluster ' + str(i))
plt.xticks(rotation=45)
plt.ylim(0,4);
3.4 可视化群集预测
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
pca_fit = pca.fit_transform(df_model)
df_pca = pd.DataFrame(data=pca_fit, columns=['PCA1', 'PCA2'])
df_pca['Clusters'] = predictions
df_pca.head()
plt.figure(figsize=(10,10))
sns.scatterplot(data=df_pca, x='PCA1', y='PCA2', hue='Clusters', palette='Set2', alpha=0.8)
plt.title('Personality Clusters after PCA');
3.5 了解我自己
我会属于哪个类别。
my_data = pd.read_excel('my_personality.xlsx')
my_personality = k_fit.predict(my_data)
print('我的个性分类: ', my_personality)
我的个性分类: [1]
# 答案分组情况
col_list = list(my_data)
ext = col_list[0:10]
est = col_list[10:20]
agr = col_list[20:30]
csn = col_list[30:40]
opn = col_list[40:50]
my_sums = pd.DataFrame()
my_sums['extroversion'] = my_data[ext].sum(axis=1)/10
my_sums['neurotic'] = my_data[est].sum(axis=1)/10
my_sums['agreeable'] = my_data[agr].sum(axis=1)/10
my_sums['conscientious'] = my_data[csn].sum(axis=1)/10
my_sums['open'] = my_data[opn].sum(axis=1)/10
my_sums['cluster'] = my_personality
print('我的问题组总数')
my_sums
我的问题组总数
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
</style>
extroversion | neurotic | agreeable | conscientious | open | cluster | |
---|---|---|---|---|---|---|
0 | 2.8 | 2.7 | 3.0 | 3.3 | 3.4 | 1 |
my_sum = my_sums.drop('cluster', axis=1)
plt.bar(my_sum.columns, my_sum.iloc[0,:], color='green', alpha=0.2)
plt.plot(my_sum.columns, my_sum.iloc[0,:], color='red')
plt.title('Cluster 2')
plt.xticks(rotation=45)
plt.ylim(0,4);
- 点赞
- 收藏
- 关注作者
评论(0)