2025 年数据科学、人工智能与机器学习职位薪资数据可视化分析
2025 年数据科学、人工智能及机器学习领域全球薪资数据可视化分析。基于 Kaggle 数据集,利用 Python 进行数据清洗与探索性分析。通过直方图、箱线图、热力图及地图展示薪资分布、年度趋势、经验等级差异、地理位置影响及远程工作模式对薪酬的影响。结果显示美国、瑞士和以色列薪资领先,高管级别溢价显著,完全远程工作平均薪资较高。分析为职业规划、招聘策略及人才培养提供数据支撑。

2025 年数据科学、人工智能及机器学习领域全球薪资数据可视化分析。基于 Kaggle 数据集,利用 Python 进行数据清洗与探索性分析。通过直方图、箱线图、热力图及地图展示薪资分布、年度趋势、经验等级差异、地理位置影响及远程工作模式对薪酬的影响。结果显示美国、瑞士和以色列薪资领先,高管级别溢价显著,完全远程工作平均薪资较高。分析为职业规划、招聘策略及人才培养提供数据支撑。

随着全球数字化转型的加速推进,数据科学、人工智能和机器学习领域在 2025 年已成为推动经济增长和技术创新的核心驱动力。企业对于具备高级数据分析能力和 AI 技术专长的人才需求呈现爆发式增长,这种需求直接反映在相关职位的薪资水平上,使得该领域成为就业市场中备受关注的高价值赛道。近年来,随着大模型技术、边缘智能和联邦学习等前沿技术的商业化落地,行业对复合型技术人才的需求结构发生了显著变化,不仅要求从业者掌握传统的编程和统计学知识,还需要具备跨学科的问题解决能力和业务场景理解力。在此背景下,全球各科技中心如硅谷、北京、班加罗尔等地区纷纷通过具有竞争力的薪酬方案来争夺顶尖人才,导致不同地域、不同细分岗位的薪资差异呈现出新的特征。与此同时,远程办公模式的普及使得人才流动的地理限制减弱,进一步加剧了企业间的人才竞争,薪资数据中开始出现传统行业与科技公司薪资趋同、新兴市场薪资增速超越发达国家等有趣现象。通过对 2025 年最新薪资数据的可视化分析,不仅可以揭示当前技术人才市场的价值分布规律,还能为从业者的职业规划、企业的招聘策略以及教育机构的人才培养方向提供数据支撑,具有重要的实践指导意义。
本实验数据集来源于 Kaggle,原始数据集共有 66063 条数据,11 个变量。各变量含义如下:
该数据集通过结合市场研究和公开数据源精心整理而成,反映了全球真实的薪酬模式。此数据集旨在支持薪资预测和机器学习建模、全球市场标杆、职业决策与谈判、远程工作趋势分析及商业智能仪表板和可视化。
导入可视化库并加载数据集

查看数据集大小

查看数据基本信息

查看数值型变量的描述性统计

查看非数值型变量的描述性统计

统计缺失值

统计重复值

发现该数据集不存在缺失值和重复值。





工资分布是右倾斜的,有大量的高收入异常值,这是典型的工资数据。对数变换给了我们一个更正态的分布,这对建模很有用。


我们可以观察到,从 2020 年到 2025 年,平均工资和中位数工资都在稳步增长,两者之间的差距略有扩大,表明该领域的不平等正在加剧。




正如预期的那样,经验水平对工资有重大影响,高管的收入远远高于其他水平。高管薪酬的增长率似乎更大,表明领导职位的溢价在上升。




在最常见的职位头衔中,机器学习工程师和研究科学家往往要求最高的薪水,而数据分析师通常收入较低。软件工程师的薪酬分布最为广泛,反映了这一职位下角色的多样性。




美国、瑞士和以色列在数据科学薪酬方面处于领先地位。




完全远程工作的平均工资往往更高。我们还可以观察到 2020 年后远程工作的重大转变(可能是由于 COVID-19 大流行),这一趋势在 2023-2024 年左右趋于稳定,但与 2020 年前的水平相比,远程工作的比例仍然更高。


大公司通常对所有经验级别的员工都提供更高的薪水,其中高管级别的差距最为明显。这反映了更大的组织拥有更多的资源和收入。




美元是全球数据科学薪酬的主要货币。汇率分析显示,随着时间的推移,货币相对强势,一些货币对美元出现贬值。



相关分析显示,工资与经验水平、公司规模和某些职位等因素之间存在很强的关系。我们可以将这些见解用于模型中的特征选择。
我们对数据科学薪酬数据集的全面分析得出了以下几点有价值的见解:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import warnings
warnings.filterwarnings('ignore')
sns.set(style="whitegrid")
plt.style.use('fivethirtyeight')
df = pd.read_csv('salaries.csv')
print(df.head())
print(df.shape)
print(df.info())
print(df.describe())
print(df.describe(include='O'))
print(df.isnull().sum())
print(df.duplicated().sum())
# 薪资分布
plt.figure(figsize=(12, 6))
sns.histplot(df['salary_in_usd'], kde=True, bins=50)
plt.title('Distribution of Salaries (USD)', fontsize=16)
plt.xlabel('Salary (USD)', fontsize=12)
plt.ylabel('Frequency', fontsize=12)
plt.axvline(df['salary_in_usd'].median(), color='red', linestyle='--', label=f'Median: ${df["salary_in_usd"].median():,}')
plt.axvline(df['salary_in_usd'].mean(), color=, linestyle=, label=)
plt.legend()
plt.show()
plt.figure(figsize=(, ))
sns.histplot(np.log1p(df[]), kde=, bins=)
plt.title(, fontsize=)
plt.xlabel(, fontsize=)
plt.ylabel(, fontsize=)
plt.show()
yearly_stats = df.groupby()[].agg([, , ]).reset_index()
fig = px.line(yearly_stats, x=, y=[, ], title=, labels={: , : , : }, template=)
fig.update_layout(legend_title_text=, hovermode=, width=, height=)
fig.add_trace(go.Scatter(
x=np.concatenate([yearly_stats[], yearly_stats[][::-]]),
y=np.concatenate([yearly_stats[] + yearly_stats[], (yearly_stats[] - yearly_stats[])[::-]]),
fill=, fillcolor=, line=(color=), name=
))
fig.show()
plt.figure(figsize=(, ))
sns.boxplot(x=, y=, data=df, order=[, , , ])
plt.title(, fontsize=)
plt.xlabel(, fontsize=)
plt.ylabel(, fontsize=)
plt.xticks(ticks=[, , , ], labels=[, , , ])
plt.show()
exp_time = df.groupby([, ])[].mean().reset_index()
exp_time[] = exp_time[].replace({: , : , : , : })
fig = px.line(exp_time, x=, y=, color=, title=, labels={: , : }, template=)
fig.update_layout(width=, height=, hovermode=)
fig.show()
top_jobs = df[].value_counts().head()
()
(top_jobs)
top_jobs_salary = df[df[].isin(top_jobs.index)].groupby()[].mean().sort_values(ascending=)
fig = px.bar(x=top_jobs_salary.index, y=top_jobs_salary.values, labels={: , : }, title=, color=top_jobs_salary.values, color_continuous_scale=)
fig.update_layout(xaxis_tickangle=-, width=, height=)
fig.show()
plt.figure(figsize=(, ))
top5_jobs = top_jobs.index[:]
sns.violinplot(x=, y=, data=df[df[].isin(top5_jobs)])
plt.title(, fontsize=)
plt.xlabel(, fontsize=)
plt.ylabel(, fontsize=)
plt.xticks(rotation=, ha=)
plt.tight_layout()
plt.show()
df[] = df[]
iso2_to_name = {: , : , : , : , : , : , : , : , : , : , : , : , : , : , : , : , : , : , : , : , : , : , : , : , : , : , : , : , : , : , : , : , : , : , : , : , : , : , : }
avg_salary_by_residence = df.groupby()[].mean().reset_index()
avg_salary_by_residence[] = avg_salary_by_residence[].(iso2_to_name)
avg_salary_by_residence = avg_salary_by_residence.dropna(subset=[])
fig2 = px.choropleth(avg_salary_by_residence, locations=, locationmode=, color=, hover_name=, hover_data={: , : }, color_continuous_scale=px.colors.sequential.Plasma, title=, labels={: }, projection=)
fig2.update_layout(width=, height=)
fig2.show()
top_countries = avg_salary_by_residence.sort_values(, ascending=).head()
plt.figure(figsize=(, ))
chart = sns.barplot(x=, y=, data=top_countries, palette=, order=top_countries[])
plt.title(, fontsize=)
plt.xlabel(, fontsize=)
plt.ylabel(, fontsize=)
plt.xticks(rotation=, ha=)
plt.grid(axis=, linestyle=, alpha=)
i, bar (chart.patches):
chart.text(bar.get_x() + bar.get_width()/, bar.get_height() + , , ha=, fontsize=)
plt.tight_layout()
plt.show()
remote_salary = df.groupby()[].agg([, , ]).reset_index()
remote_salary[] = remote_salary[].({: , : , : })
fig = px.bar(remote_salary, x=, y=[, ], barmode=, title=, labels={: , : , : }, color_discrete_sequence=[, ])
fig.update_layout(width=, height=)
fig.show()
remote_time = df.groupby([, ]).size().reset_index(name=)
total_per_year = remote_time.groupby()[].().reset_index()
remote_time = remote_time.merge(total_per_year, on=, suffixes=(, ))
remote_time[] = (remote_time[] / remote_time[]) *
remote_time[] = remote_time[].({: , : , : })
fig = px.line(remote_time, x=, y=, color=, title=, labels={: , : }, template=)
fig.update_layout(width=, height=, hovermode=)
fig.show()
company_salary = df.groupby([, ])[].median().reset_index()
company_salary[] = company_salary[].({: , : , : })
company_salary[] = company_salary[].({: , : , : , : })
fig = px.bar(company_salary, x=, y=, color=, barmode=, title=, labels={: , : }, template=)
fig.update_layout(width=, height=)
fig.show()
currency_counts = df[].value_counts().head()
fig = px.pie(values=currency_counts.values, names=currency_counts.index, title=, template=)
fig.update_traces(textposition=, textinfo=)
fig.update_layout(width=, height=)
fig.show()
df[] = df[] / df[]
top_currencies = df[].value_counts().head().index.tolist()
exchange_rates = df[df[].isin(top_currencies)].groupby([, ])[].median().reset_index()
fig = px.line(exchange_rates, x=, y=, color=, title=, labels={: , : }, template=)
fig.update_layout(width=, height=, hovermode=)
fig.show()
categorical_cols = [, , , , , , ]
numerical_cols = [, , , ]
top_job_titles = df[].value_counts().head().index.tolist()
df_corr = df[df[].isin(top_job_titles)].copy()
df_dummies = pd.get_dummies(df_corr, columns=categorical_cols, drop_first=)
corr_matrix = df_dummies.corr()
plt.figure(figsize=(, ))
sns.heatmap(corr_matrix, annot=, cmap=, center=, linewidths=)
plt.title(, fontsize=)
plt.xticks(fontsize=, rotation=)
plt.yticks(fontsize=)
plt.tight_layout()
plt.show()
salary_corr = corr_matrix[].sort_values(ascending=)
()
(salary_corr.head())
()
(salary_corr.tail())

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online