🧑 博主简介:曾任某智慧城市类企业算法总监,CSDN / 稀土掘金 等平台人工智能领域优质创作者。
目前在美国市场的物流公司从事高级算法工程师一职,深耕人工智能领域,精通python数据挖掘、可视化、机器学习等,发表过AI相关的专利并多次在AI类比赛中获奖。
一、引言
本文基于 2024-25 赛季 400+ 名土超球员的薪资明细(CSV 文件 turkish_superleague_salaries.csv),使用 Python + PyEcharts 从俱乐部、位置、年龄、国籍、合同年限、薪资结构六大维度做可视化与洞察。所有代码均可直接复制运行,生成交互式 HTML 报告,助你快速完成职场/课堂数据分析需求。

一、技术栈与数据说明
• 工具:Python 3.9、Pandas 1.5、PyEcharts 2.0
• 核心字段:Gross P/Y(年薪)、Pos.、Club、Age、Country、Years Remaining
• 预处理:
-- 去掉"€"和千位分隔符,转 float
-- 缺失年薪的三条记录(Saint-Maximin、Zaha、Mimovic)用 NaN 标记,不参与金额类可视化
-- 将 Pos. Detail 映射为 6 大类别:GK、DF、MF、FW、AM、DM
二、数据准备
python
import pandas as pd, numpy as np, pyecharts.options as opts
from pyecharts.charts import Bar, Pie, Scatter, WordCloud, HeatMap, Line, Boxplot
from pyecharts.commons.utils import JsCode
df = pd.read_csv('turkish_superleague_salaries.csv')
# 1. 金额清洗
df['Gross_P_Y_EUR'] = (
df['Gross P/Y (EUR)']
.str.replace('€', '', regex=False)
.str.replace(',', '', regex=False)
.astype(float)
)
# 2. 位置合并
pos_map = {'GK': ['GK'], 'DF': ['CB', 'LB', 'RB'],
'MF': ['CM', 'DM'], 'AM': ['AM', 'RW', 'LW', 'SS'],
'FW': ['CF']}
def map_pos(x):
for k, v in pos_map.items():
if x in v:
return k
return 'Other'
df['Pos_simple'] = df['Pos. Detail'].apply(map_pos)
# 3. 年龄分段
df['Age_group'] = pd.cut(df['Age'], bins=[0, 22, 26, 30, 35, 100],
labels=['U22', '22-26', '27-30', '31-35', '35+'])
三、六大可视化与洞察
(以下代码块均可独立运行,生成 .html 文件,浏览器直接打开查看交互)
1. 俱乐部薪资 TOP10(Bar + 自定义渐变)
python
top_club = (df.groupby('Club')['Gross_P_Y_EUR']
.agg(total='sum', avg='mean', count='size')
.sort_values('total', ascending=False)
.head(10))
bar = (
Bar()
.add_xaxis(top_club.index.tolist())
.add_yaxis("年薪总额(€)", [int(v) for v in top_club['total']])
.set_series_opts(itemstyle_opts=opts.ItemStyleOpts(
color=JsCode("new echarts.graphic.LinearGradient(0,0,0,1,[{offset:0,color:'#ff7f50'},{offset:1,color:'#1e90ff'}])")))
.set_global_opts(title_opts=opts.TitleOpts(title="俱乐部薪资 TOP10"))
)
bar.render('club_salary_top10.html')

洞察:Fenerbahce、Galatasaray、Besiktas 三强合计占全联盟 55% 薪资池;第四名差距断崖。
2. 位置薪资箱线图
python
pos_box = [df[df['Pos_simple']==p]['Gross_P_Y_EUR'].dropna().tolist()
for p in ['GK','DF','MF','AM','FW']]
box = Boxplot().add_xaxis(['GK','DF','MF','AM','FW']) \
.add_yaxis("", Boxplot.prepare_data(pos_box)) \
.set_global_opts(title_opts=opts.TitleOpts("不同位置年薪分布"))
box.render('position_box.html')

洞察:前锋(FW)与进攻型中场(AM)中位数显著高于后卫与门将,但波动极大;门将薪资最集中。
3. 年龄 vs 薪资 气泡图
python
scatter = (Scatter().add_xaxis(xaxis_data=df['Age'].tolist())\
.add_yaxis("",df['Gross_P_Y_EUR'].tolist(),color="#33FF00")\
.set_series_opts()\
.set_global_opts(
#x轴配置
xaxis_opts=opts.AxisOpts(
name ="年龄",
name_location = 'center',
name_gap = 15,
# 坐标轴类型 'value': 数值轴
type_="value",
# 分割线配置项
splitline_opts=opts.SplitLineOpts(is_show=True) #显示分割线
),
#y轴配置
yaxis_opts=opts.AxisOpts(
name ="年薪(€)",
# 坐标轴类型 'value': 数值轴
type_="value",
# 坐标轴刻度配置项
axistick_opts=opts.AxisTickOpts(is_show=True),#显示刻度
# 分割线配置项
splitline_opts=opts.SplitLineOpts(is_show=True),#显示分割线
),
# 提示框配置项
tooltip_opts=opts.TooltipOpts(is_show=False), # 不显示提示框组件
)
)
scatter.render('age_salary.html')

洞察:29-31 岁是薪资高峰,35 岁后骤降;极少数 20 岁出头新星拿到 300 万欧以上。
4. 国籍词云(仅年薪>1M)
python
from pyecharts.charts import WordCloud
country_money = (df[df['Gross_P_Y_EUR'] > 1_000_000]
.groupby('Country')['Gross_P_Y_EUR'].sum())
wc = WordCloud().add("", list(zip(country_money.index, country_money.values)),
word_size_range=[15, 80])
wc.render('country_wordcloud.html')

洞察:巴西、阿根廷、葡萄牙占据外援高薪三大帮;土耳其本土球员更多集中在中低薪区。
5. 合同年限热力图(俱乐部 × 年限)
python
hm = (df.groupby(['Club','Years Remaining']).size().unstack(fill_value=0))
x_axis, y_axis = hm.columns.astype(str).tolist(), hm.index.tolist()
value = [[i, j, int(hm.iloc[j, i])] for i in range(len(x_axis)) for j in range(len(y_axis))]
hm = (HeatMap().add_xaxis(x_axis).add_yaxis("", y_axis, value) \
.set_global_opts(title_opts=opts.TitleOpts("俱乐部合同年限分布")))
hm.render('Club_year_emaining.html')

洞察:Fenerbahce、Galatasaray 大量 3-5 年长约锁定核心;小俱乐部 1 年短约为主,转会市场更灵活。
6. 年薪结构瀑布图(分位数区间)
python
bins = [0, 0.5e6, 1e6, 2e6, 5e6, 10e6, 50e6]
labels = ['<0.5M', '0.5-1M', '1-2M', '2-5M', '5-10M', '>10M']
df['salary_band'] = pd.cut(df['Gross_P_Y_EUR'], bins=bins, labels=labels)
pie = Pie().add("", df['salary_band'].value_counts().items()) \
.set_global_opts(title_opts=opts.TitleOpts("年薪分布区间")) \
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c} ({d}%)"))
pie.render('salary_band_pie.html')

洞察:70% 球员年薪低于 100 万欧;>1000 万欧的"顶薪俱乐部"仅 6 人(Rafa Silva、Osimhen、Immobile、Icardi、Tadic、Fred)。
四、结论与业务建议
- 头部效应明显:Top3 俱乐部薪资 = 其余 17 队之和。小球队需在转会市场挖掘高性价比球员。
- 高龄溢价:30+ 球员如 Immobile、Dzeko 仍享高薪,但 35 岁后断崖;球队续约需警惕风险。
- 青年红利:U22 球员中位数仅 33 万欧,是"低买高卖"战略洼地。
- 外援结构:巴西/阿根廷/葡萄牙球员平均年薪 2.7× 本土球员,需平衡工资帽与战力。
五、一键生成综合仪表板
使用 Page 将所有图表串成单页报告:
python
from pyecharts.charts import Page
page = Page(layout=Page.SimplePageLayout)
for chart in [bar, box, scatter, wc, hm, pie]:
page.add(chart)
page.render('turkish_super_league_2024_salary_report.html')
浏览器打开 turkish_super_league_2024_salary_report.html
,即可交互式查看全部洞察。

如果您在人工智能领域遇到技术难题,或是需要专业支持,无论是技术咨询、项目开发还是个性化解决方案,我都可以为您提供专业服务,如有需要可站内私信或添加下方VX名片(ID:xf982831907)
期待与您一起交流,共同探索AI的更多可能!
<--微信名片-->