机器学习每周挑战——基于统计性分析和回归的球员薪资预测

 

背景描述

本数据集的工资数据截至 2023-24 赛季夏季转会窗口。数据提取自游戏《Football Manager 2024》,包含 40,000+ 名球员的数据。

FM24 是一款深受欢迎的足球模拟经营游戏。玩家将扮演一位足球经理,负责经营一支足球俱乐部,通过合理的人员调整、战术布置和训练安排,带领球队取得胜利。

数据说明

  • data_raw.csv
字段说明
Name球员名字
Club俱乐部
Division联赛
Based联赛举办国
Nat国籍
EU National是否为欧洲国家
Caps出场次数
AT Apps所有出场时间
Position位置
Age年龄
CR影响力(0-10000)
Begins合同开始日期
Expires合同截止日期
Last Club上一家俱乐部
Last Trans. Fee转会费
Salary工资
  • data_cleaned.csv
字段说明
Is_top_5_League是否在在五大联赛效力
Based_rich_nation球员生活的国家是否富裕
Is_top_ranked_nation球员所代表的国家是否在国际足联世界排名中名列前茅
EU_National是否为欧洲国家
Caps出场次数
Apps所有出场时间
Age年龄
Reputation影响力(0-10000)
Is_top_prev_club根据欧足联 10 年系数,前俱乐部球员是否曾在顶级俱乐部效力过
Last_Transfer_Fee转会费
Salary工资
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import plotly.express as px
import seaborn as sns
from scipy import stats
from scipy.stats import kstest,ttest_ind,spearmanr,f_oneway
from sklearn.preprocessing import StandardScaler
from statsmodels.stats.outliers_influence import variance_inflation_factor
from statsmodels.stats.stattools import durbin_watson
from sklearn.model_selection import train_test_split
import statsmodels.api as sm
from statsmodels.stats.diagnostic import het_breuschpagan
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import r2_score
from sklearn.linear_model import LinearRegression
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams['font.family'] = ['Microsoft YaHei']

 首先我们先导入用到的库,其次设置绘图时的字体为微软雅黑,防止绘图时中文出现乱码情况

df1 = pd.read_csv('D:/每周挑战/data_raw.csv')
df2 = pd.read_csv('D:/每周挑战/data_cleaned.csv')
# print(df1.info())
# print('//')
# print(df2.info())

从数据上来看df1属于未处理的数据,而df2属于清洗后的数据,因此我们分析时,只需分析清洗后的数据即可

# 虽然数据里的特征全是数值型的,但是由于含义不同,我们可以将其分为连续的和不连续的
feature1 = ['Is_top_5_League','Based_rich_nation','Is_top_ranked_nation','EU_National','Is_top_prev_club']
# for f in feature1:
#     data = df2[f].value_counts().reset_index()
#     plt.figure(figsize=(10,8))
#     sns.barplot(data,x='index',y=f)# plt.show() # 如果你的运行环境是pycharm,如果环境是jupyter notebook不建议这样写,因为这样可能导致图像无法一起显示fig,axes = plt.subplots(3,2,figsize=(16,15))
for i,f in enumerate(feature1):data = df2[f].value_counts().reset_index()fig = sns.barplot(data,x='index',y=f,ax=axes[i//2,i%2])fig.set_title(f)

feature2 = ['Caps','Apps','Age','Reputation','Last_Transfer_Fee','Salary']fig,axes = plt.subplots(3,2,figsize=(16,15))
for i,f in enumerate(feature2):data = df2[f]sns.histplot(data,ax = axes[i//2,i%2],kde=True)
#     fig.set_title(f)

 

plt.figure(figsize=(10,8))
a = df2['Last_Transfer_Fee'].reset_index()
sns.scatterplot(a,x='index',y='Last_Transfer_Fee')
plt.title('转会费分布情况')
plt.show()
plt.figure(figsize=(10,8))
b = df2['Salary'].reset_index()
sns.scatterplot(b,x='index',y='Salary')
plt.title('薪资分布情况')
plt.show()

 

 

接下来,我们可以对各个特征之间的相关性来进行判断 对于相关性的判断我们可以使用热力图,皮尔逊相关系数,斯皮尔曼相关系数等, 使用皮尔逊相关系数有一个硬性条件就是数据的分布特征必须符合正态分布,因此我们先对连续型数值数据进行KS检验

feature3 = ['Caps','Apps','Age','Reputation','Salary']   # 从上面图表可以看出转回费全是0,因此我们将其剔除
ks_result = {}
for f in feature3:ks_stats,p_value = stats.kstest(df2[f],'norm',args=(df2[f].mean(),df2[f].std()))print(f'{f}:KS statistic:{ks_stats},P-value:{p_value}.')

 

Caps:KS statistic:0.35329526602141725,P-value:0.0.
Apps:KS statistic:0.15802018198153772,P-value:0.0.
Age:KS statistic:0.08143107877963102,P-value:9.775470716540734e-236.
Reputation:KS statistic:0.03507042116880876,P-value:5.033392897827099e-44.
Salary:KS statistic:0.43688173742912745,P-value:0.0.

从这里可以看出P值没有高于0.05的,因此我们可以认为这些数据不符合正态分布,因此我们对相关性的分析可以使用斯皮尔曼

results = []
# 对连续型数据我们采用斯皮尔曼相关系数来判断其相关性
continuous_features = ['Caps','Apps','Age','Reputation','Salary']
for feature in continuous_features:corr,p_value = spearmanr(df2[feature],df2['Salary'])results.append({'Feature': feature, 'Spearman Corr': corr, 't-stat': None, 'ANOVA': None, 'p-value': p_value})# 对二分类数据我们采用t检验来判断其相关性
categorical_features = ['Is_top_5_League','Based_rich_nation','EU_National','Is_top_prev_club']
for feature in categorical_features:group0 = df2[df2[feature] == 0]['Salary']group1 = df2[df2[feature] == 1]['Salary']t_stat, p_value = ttest_ind(group0, group1)results.append({'Feature': feature, 'Spearman Corr': None, 't-stat': t_stat, 'ANOVA': None, 'p-value': p_value})# 对多分类数据我们采用方差分析来判断
anova_features = 'Is_top_ranked_nation'
group = [df2[df2[anova_features] == cat]['Salary'] for cat in sorted(df2[anova_features].unique())]
anova_stats,p_vlaue = f_oneway(*group)
results.append({'Feature':anova_features, 'Spearman Corr': None, 't-stat': None, 'ANOVA': anova_stats, 'p-value': p_value})df_results = pd.DataFrame(results)
df_results
FeatureSpearman Corrt-statANOVAp-value
0Caps0.089277NaNNaN5.846491e-73
1Apps0.517847NaNNaN0.000000e+00
2Age0.249744NaNNaN0.000000e+00
3Reputation0.833983NaNNaN0.000000e+00
4Salary1.000000NaNNaN0.000000e+00
5Is_top_5_LeagueNaN-35.837645NaN5.814363e-277
6Based_rich_nationNaN-14.167243NaN1.873582e-45
7EU_NationalNaN-2.128449NaN3.330584e-02
8Is_top_prev_clubNaN-33.013365NaN6.765112e-236
9Is_top_ranked_nationNaNNaN34.9306316.765112e-236

出场次数与球员工资之间的斯皮尔曼相关系数为 0.089,表示两者之间有很弱的正相关性。 所有出场时间与球员工资之间的斯皮尔曼相关系数为 0.518,表明有中等程度的正相关性。 年龄与球员工资之间的斯皮尔曼相关系数为 0.250,显示两者间有较弱的正相关性。 影响力与球员工资之间的斯皮尔曼相关系数为 0.834,表明两者之间有较强的正相关性。 Is_top_5_League: t检验的t值为 -35.84,p值非常小,表明是否在在五大联赛效力与球员工资存在显著差异。 Based_rich_nation: t检验的t值为 -14.17,p值非常小,表示球员生活的国家是否富裕与球员工资之间存在显著差异。 EU_National: t检验的t值为 -2.13,p值为0.033,显示是否为欧洲国家与球员工资之间的差异在统计学上显著。 Is_top_prev_club: t检验的t值为 -33.01,p值非常小,显示前俱乐部球员是否曾在顶级俱乐部效力过与球员工资之间有显著差异。 Is_top_ranked_nation: 方差分析的F值为 34.93,p值非常小,表明球员所代表的国家是否在国际足联世界排名中名列前茅在不同组别中对球员工资有显著的影响。

模型的建立,由于部分数据跨度较大,因此我们先对数据进行标准化,之后计算VIF值,确定其不存在多重共线性。 这里我们又用到了多元线性回归模型,因此步骤还是老步骤,首先对残差进行正态性,独立性,同方差性进行检验

data = df2.copy()
data = data.drop('Last_Transfer_Fee',axis=1)
feature4 = ['Caps','Apps','Age','Reputation']
scaler = StandardScaler()data[feature4] = scaler.fit_transform(data[feature4])# 由于目标值不符合正态分布,因此我们对目标值进行对数变换,使其更加接近于正态分布
data['Log_Salary'] = np.log(data['Salary'])# 接下来我们计算各个特征的VIF值,确定其是否存在多重共线性
X = data.drop(['Salary','Log_Salary'],axis=1)
y = data['Salary']VIF_data = pd.DataFrame()
VIF_data['feature'] = X.columns
VIF_data['VIF_values'] = [variance_inflation_factor(X.values,i) for i in range(X.shape[1])]
VIF_data
featureVIF_values
0Is_top_5_League1.391285
1Based_rich_nation3.278526
2Is_top_ranked_nation3.251428
3EU_National3.027021
4Caps1.228038
5Apps3.205145
6Age2.970727
7Reputation1.429138
8Is_top_prev_club1.081392

可以看出VIF值基本都在1-4之间,因此我们可以判断出,数据中不存在多重共线性 接下来,我们开始对数据集进行建模

data.drop('Salary',axis=1,inplace=True)X = data.drop('Log_Salary',axis=1)
y = data['Log_Salary']X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.3,random_state=42)line_model = LinearRegression()
line_model.fit(X_train,y_train)
y_pred = line_model.predict(X_train)
residuals = y_train - y_predDW = durbin_watson(residuals)
print('DW值:',DW)
DW值: 1.9994671572216502

这里可以看出DW值在2附近,因此我们可以看出线性回归的残差独立性是比较好的,接下来我们对残差的正态性和同方差性进行检验

# KS检验
ks_statistic,ks_pvalues = kstest((residuals - np.mean(residuals))/ np.std(residuals),'norm')
print(f'KS检验:{ks_statistic},P值:{ks_pvalues}')
KS检验:0.029053858860392467,P值:2.2584717876590108e-21
# 增加常数项到自变量矩阵中,因为线性回归模型默认包含截距
X_constant = sm.add_constant(X_train)
# Breusch-Pagan检验
bp_test = het_breuschpagan(residuals,X_constant)
labels = ['Lagrange multiplier statistic', 'p-value', 'f-value', 'f p-value']
print(dict(zip(labels, bp_test)))
{'Lagrange multiplier statistic': 1643.1994698959277, 'p-value': 0.0, 'f-value': 193.65865696721104, 'f p-value': 0.0}

从P-value可以看出,残差并没有通过同方差性检验,因此我们就不使用多元线性回归模型来进行预测了 因此我们接下来使用随机森林来进行预测

Rtree = RandomForestRegressor()
Rtree.fit(X_train,y_train)y_pred = Rtree.predict(X_test)
R2 = r2_score(y_test,y_pred)print('R2系数:',R2)
R2系数: 0.7949048167355701
important_feature = Rtree.feature_importances_
feature = X.columnssort_index = important_feature.argsort()plt.figure(figsize=(12, 6))
plt.barh(range(len(sort_index)), important_feature[sort_index])
plt.yticks(range(len(sort_index)), [feature[i] for i in sort_index])
plt.xlabel('特征重要性')
plt.title('特征重要性分析')plt.show()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/681179.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DDR5和LPDDR4/5 命令解析

关键名称介绍 DDR5 SDRAM和LPDDR4/5都采用了高级的命令集来支持更高效的内存管理和操作,其中“Multi-purpose command (MPC)”、“Mode Register Read (MRR)”、“Mode Register Write (MRW)”,以及“Write Pattern Command”是几种关键的命令类型,它们在内存初始化、配置和…

家装空间3D建模素材:打造理想家园的必备工具

在家装过程中,设计师和业主往往需要通过3D建模技术来实现对空间的精确规划和设计。3D建模素材作为这一领域的基础元素,为设计师提供了丰富的想象空间,帮助他们更好地呈现业主的期望和需求。 这些3D建模素材可以涵盖各种家装元素,如…

喜讯!莱佛士学生成功入围2024C-IDEA设计奖提名

近日,由澳大利亚平面设计协会、韩国视觉信息设计协会、波兰波兹南设计节、日本字体设计协会(JTA)、俄罗斯设计师协会、中国台湾高雄广告创意协会多家不同的国际设计机构联合发起组织的国际性设计赛事—— C-IDEA设计奖,公布了2024…

vue3创建响应式数据ref和reactive的区别

reactive和ref在Vue.js中都是用于创建响应式数据的,但它们之间存在一些区别 定义数据类型不同。ref主要用于定义基本数据类型,如字符串、数字、布尔值等;reactive主要用于定义对象(或数组)类型的数据,但re…

深度学习:基于TensorFlow 和 Keras,使用神经网络回归模型预测 IPL 分数

前言 系列专栏:机器学习:高级应用与实践【项目实战100】【2024】✨︎ 在本专栏中不仅包含一些适合初学者的最新机器学习项目,每个项目都处理一组不同的问题,包括监督和无监督学习、分类、回归和聚类,而且涉及创建深度学…

小米SU7智能座舱揭秘:五音区语音交互,智能语音新体验

“小爱同学,打开右后方车门。” “小爱同学,前面的山是什么山?” “小爱同学,有没有离簋街和望京都比较近的川菜馆?” “小爱同学,右后视镜向外调20%,左后视镜往里调10%。” “小爱同学&#xf…

5分钟了解下HDFS

随着大数据时代的到来,传统的数据存储和管理方式已经无法满足日益增长的数据处理需求。HDFS(Hadoop Distributed File System)作为Apache Hadoop项目的一部分,以其高度的容错性、可扩展性和高吞吐量,成为了处理大规模数…

[C/C++] -- 代理模式

代理模式是一种结构型设计模式,允许一个对象(代理)控制另一个对象的访问。代理对象通常充当客户端和实际目标对象之间的中间人,从而控制对目标对象的访问,可以在访问前后进行一些额外的处理。 代理模式的优点包括&…

linux代码实操——信号的使用

信号的基本概念 信号是系统响应某个条件而产生的事件,进程接收到信号会执行相应的操作。 与信号有关的系统调用在“signal.h”头文件中有声明 常见信号的值,及对应的功能说明: 修改信号的响应方式 – signal() 我们来做个小实验: 在键盘上…

【设计模式】JAVA Design Patterns——Abstract-document

🔍 目的 使用动态属性,并在保持类型安全的同时实现非类型化语言的灵活性。 🔍 解释 抽象文档模式使您能够处理其他非静态属性。 此模式使用特征的概念来实现类型安全,并将不同类的属性分离为一组接口 真实世界例子 考虑由多个部…

Java面试八股文(SpringCloud篇)

****************************************************

【编程基础】人人都应该懂得递归小知识

文章目录 什么是递归递归和栈尾递归递归和分治归并排序 递归和树 什么是递归 下面引用刘汝佳的《算法竞赛入门经典》中对递归的定义: 递归:参见递归。递归:如果你还不理解递归是什么,请参见递归。 递归事实上就是函数直接或间接…