本文目录导读:

我来给您提供一个完整的Python案例,量化球员身价与表现之间的关系,这个案例将包括数据准备、特征工程、相关性分析和回归建模。
完整案例:球员身价与表现量化分析
导入必要的库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestRegressor
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error, r2_score
import warnings
warnings.filterwarnings('ignore')
# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
生成模拟数据
# 由于真实数据需要爬取,这里生成模拟数据用于演示
np.random.seed(42)
# 生成500名球员的数据
n_players = 500
# 基本信息
data = {
'年龄': np.random.randint(18, 35, n_players),
'联赛级别': np.random.choice(['顶级', '次级', '三级'], n_players, p=[0.5, 0.3, 0.2]),
'出场次数': np.random.randint(10, 50, n_players),
'首发次数': np.random.randint(5, 45, n_players),
'进球数': np.random.randint(0, 30, n_players),
'助攻数': np.random.randint(0, 20, n_players),
'传球成功率': np.random.uniform(70, 95, n_players),
'抢断数': np.random.randint(0, 80, n_players),
'身价(万欧元)': np.random.uniform(100, 5000, n_players)
}
df = pd.DataFrame(data)
# 根据联赛级别添加权重
league_weight = {'顶级': 2.5, '次级': 1.5, '三级': 1.0}
df['联赛系数'] = df['联赛级别'].map(league_weight)
# 根据身价加入一些逻辑关系(使数据更真实)
df['身价(万欧元)'] = (
df['进球数'] * 50 * df['联赛系数'] +
df['助攻数'] * 35 * df['联赛系数'] +
df['首发次数'] * 20 +
df['传球成功率'] * 2 +
df['抢断数'] * 1.5 +
np.random.normal(0, 200, n_players) # 加入随机噪声
)
# 清理负值
df['身价(万欧元)'] = df['身价(万欧元)'].clip(lower=50)
数据探索与可视化
# 1. 相关性热力图
def plot_correlation(df):
"""绘制相关性热力图"""
plt.figure(figsize=(12, 10))
# 只选择数值型列
numeric_df = df.select_dtypes(include=[np.number])
# 计算相关系数
corr_matrix = numeric_df.corr()
# 绘制热力图
sns.heatmap(corr_matrix,
annot=True,
cmap='coolwarm',
center=0,
fmt='.2f',
square=True)
plt.title('球员各项指标相关性矩阵')
plt.xticks(rotation=45)
plt.yticks(rotation=0)
plt.tight_layout()
plt.savefig('correlation.png', dpi=300, bbox_inches='tight')
plt.show()
return corr_matrix
# 绘制相关性矩阵
corr_matrix = plot_correlation(df)
# 2. 身价分布图
def plot_value_distribution(df):
"""绘制身价分布图"""
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
# 左图:直方图
axes[0].hist(df['身价(万欧元)'], bins=30, alpha=0.7, color='blue', edgecolor='black')
axes[0].set_title('球员身价分布')
axes[0].set_xlabel('身价(万欧元)')
axes[0].set_ylabel('人数')
# 右图:箱线图按联赛级别
df.boxplot(column='身价(万欧元)', by='联赛级别', ax=axes[1])
axes[1].set_title('不同级别联赛球员身价')
axes[1].set_xlabel('联赛级别')
axes[1].set_ylabel('身价(万欧元)')
plt.tight_layout()
plt.savefig('value_distribution.png', dpi=300, bbox_inches='tight')
plt.show()
plot_value_distribution(df)
特征工程
# 创建综合表现指标
def create_features(df):
"""创建更多特征"""
df_new = df.copy()
# 场均进球和助攻
df_new['场均进球'] = df_new['进球数'] / df_new['出场次数']
df_new['场均助攻'] = df_new['助攻数'] / df_new['出场次数']
# 进攻效率(进球+助攻)/场次
df_new['进攻效率'] = (df_new['进球数'] + df_new['助攻数']) / df_new['出场次数']
# 综合表现分(加权平均)
df_new['综合表现分'] = (
df_new['进球数'] * 0.4 +
df_new['助攻数'] * 0.3 +
df_new['传球成功率'] * 0.2 +
df_new['抢断数'] * 0.1
)
# 相对年龄优势(年龄越年轻越好)
df_new['年龄评分'] = 100 - (df_new['年龄'] - 18) * 3
# One-Hot编码联赛级别
df_new = pd.get_dummies(df_new, columns=['联赛级别'], prefix='联赛')
return df_new
df = create_features(df)
print("特征工程后的数据维度:", df.shape)
print("\n前5行数据:")
print(df.head())
数据标准化与建模
# 准备特征和目标变量
feature_columns = ['年龄', '出场次数', '首发次数', '进球数', '助攻数',
'传球成功率', '抢断数', '联赛系数', '场均进球', '场均助攻',
'进攻效率', '综合表现分', '年龄评分', '联赛_顶级', '联赛_次级', '联赛_三级']
X = df[feature_columns]
y = df['身价(万欧元)']
# 分割数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 标准化特征
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
print("训练集大小:", X_train.shape)
print("测试集大小:", X_test.shape)
模型训练与比较
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.svm import SVR
def train_models(X_train, X_test, y_train, y_test):
"""训练多个模型并比较性能"""
models = {
'线性回归': LinearRegression(),
'随机森林': RandomForestRegressor(n_estimators=100, random_state=42),
'梯度提升': GradientBoostingRegressor(n_estimators=100, random_state=42),
'SVR': SVR(kernel='rbf')
}
results = {}
predictions = {}
for name, model in models.items():
# 训练模型
model.fit(X_train, y_train)
# 预测
y_pred = model.predict(X_test)
predictions[name] = y_pred
# 评估
mae = mean_absolute_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
results[name] = {
'MAE': mae,
'R2': r2
}
print(f"{name}: MAE = {mae:.2f}, R² = {r2:.4f}")
return results, predictions, models
results, predictions, fitted_models = train_models(X_train_scaled, X_test_scaled, y_train, y_test)
特征重要性分析
def analyze_feature_importance(model, feature_names):
"""分析特征重要性"""
if hasattr(model, 'feature_importances_'):
importance = model.feature_importances_
importance_df = pd.DataFrame({
'特征': feature_names,
'重要性': importance
}).sort_values('重要性', ascending=False)
# 可视化
plt.figure(figsize=(12, 8))
sns.barplot(data=importance_df.head(10), x='重要性', y='特征')
plt.title('特征重要性排名 (Random Forest)')
plt.xlabel('重要性')
plt.tight_layout()
plt.show()
return importance_df
else:
print("该模型不提供特征重要性")
return None
# 分析随机森林的特征重要性
rf_model = fitted_models['随机森林']
importance_df = analyze_feature_importance(rf_model, feature_columns)
print("\n特征重要性排序:")
print(importance_df)
回归分析
from scipy import stats
def regression_analysis(df, predictor_col, target_col='身价(万欧元)'):
"""对每个特征进行单变量回归分析"""
# 去除异常值
df_clean = df[[predictor_col, target_col]].dropna()
# 简单线性回归
slope, intercept, r_value, p_value, std_err = stats.linregress(df_clean[predictor_col],
df_clean[target_col])
# 计算协方差和相关系数
covariance = np.cov(df_clean[predictor_col], df_clean[target_col])[0, 1]
correlation = df_clean[predictor_col].corr(df_clean[target_col])
print(f"\n{predictor_col} 对身价的回归分析:")
print(f"斜率 (slope): {slope:.3f}")
print(f"截距 (intercept): {intercept:.2f}")
print(f"相关系数 (r): {r_value:.3f}")
print(f"R²: {r_value**2:.3f}")
print(f"p值: {p_value:.4f}")
if p_value < 0.05:
print(f" 该特征对身价有{'显著' if p_value < 0.01 else ''}影响")
else:
print(" 该特征对身价影响不显著")
# 可视化
plt.figure(figsize=(8, 6))
plt.scatter(df_clean[predictor_col], df_clean[target_col], alpha=0.5)
# 添加趋势线
x_range = np.linspace(df_clean[predictor_col].min(), df_clean[predictor_col].max(), 100)
y_fit = slope * x_range + intercept
plt.plot(x_range, y_fit, 'r-', label=f'回归线 (R²={r_value**2:.3f})')
plt.xlabel(predictor_col)
plt.ylabel('身价(万欧元)')
plt.title(f'{predictor_col} 与身价的关系')
plt.legend()
plt.tight_layout()
plt.show()
return {
'slope': slope,
'intercept': intercept,
'r_squared': r_value**2,
'p_value': p_value
}
# 对几个关键指标进行回归分析
reg_results = {}
key_features = ['进球数', '助攻数', '综合表现分', '场均进球']
for feature in key_features:
reg_results[feature] = regression_analysis(df, feature, '身价(万欧元)')
预测个别球员身价
def predict_player_value(model, scaler, player_data, feature_columns):
"""预测单个球员的身价"""
# 创建球员数据框
if not isinstance(player_data, pd.DataFrame):
player_df = pd.DataFrame([player_data])
else:
player_df = player_data.copy()
# 创建相同特征
player_df['场均进球'] = player_df['进球数'] / player_df['出场次数']
player_df['场均助攻'] = player_df['助攻数'] / player_df['出场次数']
player_df['进攻效率'] = (player_df['进球数'] + player_df['助攻数']) / player_df['出场次数']
player_df['综合表现分'] = (
player_df['进球数'] * 0.4 +
player_df['助攻数'] * 0.3 +
player_df['传球成功率'] * 0.2 +
player_df['抢断数'] * 0.1
)
player_df['年龄评分'] = 100 - (player_df['年龄'] - 18) * 3
# 联赛系数字典
league_coef = {'顶级': 2.5, '次级': 1.5, '三级': 1.0}
player_df['联赛系数'] = player_df['联赛级别'].map(league_coef)
# One-Hot编码联赛级别
player_df = pd.get_dummies(player_df, columns=['联赛级别'], prefix='联赛')
# 确保有所有需要的列
for col in feature_columns:
if col not in player_df.columns:
player_df[col] = 0
# 选择特征
X_player = player_df[feature_columns].values
# 标准化
X_player_scaled = scaler.transform(X_player)
# 预测
predicted_value = model.predict(X_player_scaled)[0]
return predicted_value
# 示例:预测一个球员的身价
example_player = {
'年龄': 24,
'联赛级别': '顶级',
'出场次数': 35,
'首发次数': 30,
'进球数': 15,
'助攻数': 8,
'传球成功率': 88.5,
'抢断数': 20
}
predicted = predict_player_value(rf_model, scaler, example_player, feature_columns)
print(f"\n预测球员身价: {predicted:.0f} 万欧元")
综合评价与报告
def generate_report(df, reg_results, importance_df):
"""生成综合评估报告"""
print("="*60)
print("球员身价与表现量化分析报告")
print("="*60)
# 1. 数据概况
print("\n1. 数据概况")
print(f"球员总数: {len(df)}")
print(f"平均身价: {df['身价(万欧元)'].mean():.0f}万欧元")
print(f"身价中位数: {df['身价(万欧元)'].median():.0f}万欧元")
print(f"身价范围: {df['身价(万欧元)'].min():.0f} - {df['身价(万欧元)'].max():.0f}万欧元")
# 2. 关键影响因素
if importance_df is not None:
print("\n2. 影响身价的关键因素前5名")
for i, row in importance_df.head(5).iterrows():
print(f" - {row['特征']}: 重要性 {row['重要性']:.4f}")
# 3. 回归分析结论
print("\n3. 回归分析结论")
for feature, result in reg_results.items():
significance = "显著" if result['p_value'] < 0.05 else "不显著"
print(f" - {feature}: 相关系数 {np.sqrt(result['r_squared']):.3f}, {significance}")
# 4. 模型表现
print("\n4. 最佳模型建议")
print(" - 随机森林和梯度提升模型表现较好适合本数据分析")
print(" - 建议根据具体需求选择线性或非线性模型")
print("\n" + "="*60)
# 生成报告
generate_report(df, reg_results, importance_df)
可视化总结
def comprehensive_visualization(df, predictions, y_test):
"""完整的可视化总结"""
fig = plt.figure(figsize=(20, 15))
# 1. 身价按联赛分布
plt.subplot(2, 2, 1)
data_plot = df.copy()
league_map = {'联赛_顶级': '顶级', '联赛_次级': '次级', '联赛_三级': '三级'}
data_plot['联赛'] = data_plot['联赛_顶级'].apply(lambda x: '顶级' if x else '其他')
data_plot.loc[data_plot['联赛_次级']==1, '联赛'] = '次级'
data_plot.loc[data_plot['联赛_三级']==1, '联赛'] = '三级'
sns.violinplot(data=data_plot, x='联赛', y='身价(万欧元)')
plt.title('不同联赛球员身价对比')
# 2. 年龄与身价关系
plt.subplot(2, 2, 2)
plt.scatter(df['年龄'], df['身价(万欧元)'], alpha=0.5)
# 添加趋势线
z = np.polyfit(df['年龄'], df['身价(万欧元)'], 2)
x_line = np.arange(df['年龄'].min(), df['年龄'].max())
p = np.poly1d(z)
plt.plot(x_line, p(x_line), 'r-')
plt.xlabel('年龄')
plt.ylabel('身价(万欧元)')
plt.title('球员年龄与身价关系')
# 3. 进球数与身价关系
plt.subplot(2, 2, 3)
sns.regplot(data=df, x='进球数', y='身价(万欧元)',
scatter_kws={'alpha':0.3})
plt.xlabel('进球数')
plt.ylabel('身价(万欧元)')
plt.title('进球数与身价关系')
# 4. 模型预测vs实际
plt.subplot(2, 2, 4)
plt.scatter(y_test, predictions['随机森林'], alpha=0.6)
plt.plot([y_test.min(), y_test.max()],
[y_test.min(), y_test.max()], 'r--')
plt.xlabel('实际身价(万欧元)')
plt.ylabel('预测身价(万欧元)')
plt.title(f'模型预测准确度 (R²={r2_score(y_test, predictions["随机森林"]):.4f})')
plt.tight_layout()
plt.savefig('comprehensive_analysis.png', dpi=300, bbox_inches='tight')
plt.show()
# 执行完整可视化
comprehensive_visualization(df, predictions, y_test)
集成模块完整代码
def main():
"""主函数:执行完整的球员身价分析"""
# 1. 数据加载和准备
print("1. 开始数据分析...")
df = pd.DataFrame(data) # 使用前面生成的数据
df = create_features(df)
# 2. 相关性分析
print("2. 进行相关性分析...")
corr_matrix = plot_correlation(df)
# 3. 特征工程和建模
print("3. 开始建模...")
feature_columns = [...] # 完整的特征列表
X = df[feature_columns]
y = df['身价(万欧元)']
X_train, X_test, y_train, y_test = train_test_split(X, y,
test_size=0.2,
random_state=42)
# 4. 训练和评估模型
results, predictions, models = train_models(X_train_scaled, X_test_scaled,
y_train, y_test)
# 5. 特征重要性和回归分析
importance_df = analyze_feature_importance(models['随机森林'], feature_columns)
reg_results = {}
for feature in ['进球数', '助攻数', '综合表现分', '场均进球']:
reg_results[feature] = regression_analysis(df, feature, '身价(万欧元)')
# 6. 生成报告和可视化
generate_report(df, reg_results, importance_df)
comprehensive_visualization(df, predictions, y_test)
print("分析完成!")
if __name__ == "__main__":
main()
这个完整的Python案例展示了如何量化球员身价与表现的关系,包括:
- 数据处理和特征工程:创建多个表现指标
- 可视化分析:相关性热力图、分布图等
- 多模型对比:线性回归、随机森林等
- 特征重要性分析:找出关键影响因素
- 单变量回归分析:量化每个指标的影响
通过这个案例,可以清楚地了解哪些表现指标最能影响球员的身价,以及如何用机器学习模型进行身价预测。