1. 引言
1.1 背景
数据可视化是数据分析的重要环节,通过图表可以:
- 发现模式:识别数据中的趋势、异常和关系
- 传达信息:将复杂数据转化为易于理解的视觉形式
- 支持决策:为业务决策提供直观的数据支持
- 展示结果:在报告和演示中展示分析结果
对于数据分析师、数据科学家、学生和教育工作者来说,掌握数据可视化技能是必备能力。然而,很多初学者在面对数据可视化时,往往不知道:
- 应该选择哪种图表类型?
- 如何让图表更专业、更美观?
- 如何优化图表的视觉效果?
1.2 应用场景
- 数据探索和发现:通过可视化快速了解数据特征
- 数据分析和报告:在报告和演示中展示分析结果
- 数据可视化学习案例:作为教学示例,学习各种图表类型
- AI项目周期实践示例:完整展示AI项目从需求到部署的全流程
2. 项目概述
2.1 项目目标
掌握常用的数据可视化技术,包括基础图表、统计图表、高级可视化等,能够根据数据类型和目标选择合适的图表类型。
2.2 任务类型
- 任务类型:数据可视化、数据分析
- 目标:创建专业、美观、清晰的数据图表
2.3 技术栈
- 数据处理:Pandas、NumPy
- 数据可视化:Matplotlib、Seaborn
- 图表类型:柱状图、折线图、散点图、饼图、直方图、箱线图、热力图、小提琴图等
2.4 数据集
- 数据集名称:员工离职数据集
- 数据文件 :
Dataset_Employee_Attrition_Train.csv(训练数据)Dataset_Employee_Attrition_Test.csv(测试数据)
- 主要特征 :
Age: 年龄Gender: 性别Time_of_service: 服务时长Attrition_rate: 离职率Education_Level: 教育水平Unit: 部门- 其他数值型特征(VAR1-VAR7等)
3. AI项目周期6个阶段详解
阶段1:需求界定
3.1.1 问题定义
数据可视化是数据分析的重要环节,通过图表可以:
- 发现模式:识别数据中的趋势、异常和关系
- 传达信息:将复杂数据转化为易于理解的视觉形式
- 支持决策:为业务决策提供直观的数据支持
- 展示结果:在报告和演示中展示分析结果
目标:
- 掌握Python数据可视化的基础技能
- 学习常用图表类型的适用场景
- 了解如何优化图表的视觉效果
- 创建专业的数据可视化报告
阶段2:数据获取
3.2.1 环境准备
在开始项目之前,需要安装必要的库:
required_libraries = {
"numpy": None,
"pandas": None,
"matplotlib": None,
"seaborn": None,
"sklearn": None
}
from utilities.utils import check_and_install
check_and_install(required_libraries)
3.2.2 数据加载
import os
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# 数据文件路径
train_file = "Dataset_Employee_Attrition_Train.csv"
test_file = "Dataset_Employee_Attrition_Test.csv"
# 检查文件是否存在并加载数据
if os.path.exists(train_file):
train = pd.read_csv(train_file)
print(f"✅ 训练数据加载成功: {train.shape}")
else:
print(f"❌ 错误: 找不到数据文件 {train_file}")
if os.path.exists(test_file):
test = pd.read_csv(test_file)
print(f"✅ 测试数据加载成功: {test.shape}")
3.2.3 数据预处理
为了创建各种可视化所需的数据集,我们需要对原始数据进行预处理:
# 1. 时间序列数据(用于折线图)- 基于员工服务时长分组统计
time_service_data = train.groupby('Time_of_service')['Attrition_rate'].mean().reset_index()
time_service_data.columns = ['服务时长', '平均离职率']
time_service_data = time_service_data.sort_values('服务时长')
# 2. 分类数据(用于柱状图、饼图)- 按性别统计
gender_data = train['Gender'].value_counts().reset_index()
gender_data.columns = ['性别', '数量']
gender_data['占比'] = (gender_data['数量'] / gender_data['数量'].sum() * 100).round(1)
# 3. 连续数据(用于直方图、散点图)- 年龄和离职率
continuous_data = train[['Age', 'Attrition_rate', 'Education_Level']].copy()
continuous_data.columns = ['年龄', '离职率', '教育水平']
# 4. 相关性数据(用于热力图、散点图矩阵)- 选择数值型特征
numeric_cols = ['Age', 'Time_of_service', 'Time_since_promotion',
'growth_rate', 'Travel_Rate', 'Post_Level', 'Education_Level',
'VAR1', 'VAR2', 'VAR3', 'VAR4', 'VAR5', 'VAR6', 'VAR7', 'Attrition_rate']
available_cols = [col for col in numeric_cols if col in train.columns]
correlation_data = train[available_cols].copy()
# 5. 分组数据(用于分组柱状图、箱线图)- 按部门分组
if 'Unit' in train.columns:
group_data = train[['Unit', 'Attrition_rate']].copy()
group_data.columns = ['部门', '离职率']
else:
group_data = train[['Education_Level', 'Attrition_rate']].copy()
group_data.columns = ['教育水平', '离职率']
print("=" * 60)
print("数据加载和预处理完成")
print("=" * 60)
print(f"✅ 训练数据: {train.shape}")
print(f"✅ 时间序列数据: {time_service_data.shape}")
print(f"✅ 分类数据: {gender_data.shape}")
print(f"✅ 连续数据: {continuous_data.shape}")
print(f"✅ 相关性数据: {correlation_data.shape}")
print(f"✅ 分组数据: {group_data.shape}")
知识点:
- 根据不同的可视化需求,准备不同类型的数据
- 使用
groupby()进行数据分组统计 - 使用
value_counts()统计分类数据的频数
阶段3:数据分析
3.3.1 数据概览
# 查看各类数据的基本信息
print("=" * 60)
print("数据概览")
print("=" * 60)
print("1. 训练数据基本信息:")
print(f"数据形状: {train.shape[0]} 行 × {train.shape[1]} 列")
print(f"列名:")
print(train.columns.tolist())
print("前5行数据:")
print(train.head())
print("2. 时间序列数据(服务时长与离职率):")
print(time_service_data.head(10))
print("3. 分类数据(性别分布):")
print(gender_data)
print("4. 连续数据统计信息(年龄和离职率):")
print(continuous_data.describe())
print("5. 相关性数据统计信息:")
print(correlation_data.describe())
知识点:
- 使用
info()查看数据基本信息 - 使用
describe()查看数值型特征的统计信息 - 使用
head()查看前几行数据
阶段4:模型构建(图表创建)
在数据可视化中,"模型构建"指的是选择可视化工具、设计并创建图表的过程。
4.1 基础图表:柱状图(Bar Chart)
柱状图用于比较不同类别的数值大小,适合展示分类数据。
# 设置中文字体
plt.rcParams['font.family'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False
# 创建柱状图
plt.figure(figsize=(10, 6))
plt.bar(gender_data['性别'], gender_data['数量'],
color=['#FF6B6B', '#4ECDC4'])
plt.xlabel('性别', fontsize=12)
plt.ylabel('数量', fontsize=12)
plt.title('员工性别分布(柱状图)', fontsize=14, fontweight='bold')
plt.grid(axis='y', alpha=0.3)
# 在柱子上添加数值标签
for i, v in enumerate(gender_data['数量']):
plt.text(i, v + 1, str(v), ha='center', va='bottom', fontsize=10)
plt.tight_layout()
plt.show()
print("💡 适用场景:比较不同类别的数值大小")
知识点:
- 使用
plt.bar()创建柱状图 - 使用
plt.text()在柱子上添加数值标签 - 使用
plt.grid()添加网格线提高可读性
4.2 基础图表:折线图(Line Chart)
折线图用于展示数据随时间的变化趋势,适合时间序列数据。
# 创建折线图
plt.figure(figsize=(12, 6))
plt.plot(time_service_data['服务时长'], time_service_data['平均离职率'],
marker='o', linewidth=2, label='平均离职率', color='#4ECDC4', markersize=6)
plt.xlabel('服务时长(年)', fontsize=12)
plt.ylabel('平均离职率', fontsize=12)
plt.title('服务时长与平均离职率的关系(折线图)', fontsize=14, fontweight='bold')
plt.legend(fontsize=11)
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
print("💡 适用场景:展示数据随时间的变化趋势")
知识点:
- 使用
plt.plot()创建折线图 - 使用
marker参数添加标记点 - 使用
plt.legend()添加图例
4.3 基础图表:散点图(Scatter Plot)
散点图用于展示两个变量之间的关系,适合发现相关性。
# 创建散点图
plt.figure(figsize=(10, 6))
plt.scatter(continuous_data['年龄'], continuous_data['离职率'],
alpha=0.6, s=50, color='#45B7D1')
plt.xlabel('年龄', fontsize=12)
plt.ylabel('离职率', fontsize=12)
plt.title('年龄与离职率的关系(散点图)', fontsize=14, fontweight='bold')
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
print("💡 适用场景:展示两个变量之间的关系,发现相关性")
知识点:
- 使用
plt.scatter()创建散点图 - 使用
alpha参数设置透明度 - 使用
s参数设置点的大小
4.4 基础图表:饼图(Pie Chart)
饼图用于展示各部分占整体的比例,适合展示分类数据的占比。
# 创建饼图
plt.figure(figsize=(8, 8))
colors = ['#FF6B6B', '#4ECDC4']
plt.pie(gender_data['数量'], labels=gender_data['性别'],
autopct='%1.1f%%', startangle=90, colors=colors)
plt.title('员工性别分布(饼图)', fontsize=14, fontweight='bold')
plt.tight_layout()
plt.show()
print("💡 适用场景:展示各部分占整体的比例")
知识点:
- 使用
plt.pie()创建饼图 - 使用
autopct参数显示百分比 - 使用
startangle参数设置起始角度
4.5 统计图表:直方图(Histogram)
直方图用于展示数据的分布情况,适合连续数据。
# 创建直方图
plt.figure(figsize=(10, 6))
plt.hist(continuous_data['年龄'], bins=30, edgecolor='black',
alpha=0.7, color='#4ECDC4')
plt.xlabel('年龄', fontsize=12)
plt.ylabel('频数', fontsize=12)
plt.title('员工年龄分布(直方图)', fontsize=14, fontweight='bold')
plt.grid(axis='y', alpha=0.3)
plt.tight_layout()
plt.show()
print("💡 适用场景:展示数据的分布情况")
知识点:
- 使用
plt.hist()创建直方图 - 使用
bins参数设置分组数量 - 使用
edgecolor参数设置边框颜色
4.6 统计图表:箱线图(Box Plot)
箱线图用于展示数据的分布、中位数、四分位数和异常值。
# 创建箱线图
plt.figure(figsize=(10, 6))
departments = group_data['部门'].unique()
box_data = [group_data[group_data['部门']==dept]['离职率'].values for dept in departments]
plt.boxplot(box_data, labels=departments)
plt.ylabel('离职率', fontsize=12)
plt.title('不同部门的离职率分布(箱线图)', fontsize=14, fontweight='bold')
plt.grid(axis='y', alpha=0.3)
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
print("💡 适用场景:展示数据的分布、中位数、四分位数和异常值")
知识点:
- 使用
plt.boxplot()创建箱线图 - 箱线图可以显示中位数、四分位数、异常值等统计信息
4.7 高级图表:热力图(Heatmap)
热力图用于展示矩阵数据的相关性或强度,适合展示多变量关系。
# 创建热力图
plt.figure(figsize=(10, 8))
correlation_matrix = correlation_data.corr()
ax = sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', center=0,
square=True, linewidths=0.5, fmt='.2f')
plt.title('特征相关性热力图', fontsize=14, fontweight='bold')
plt.tight_layout()
plt.show()
print("💡 适用场景:展示矩阵数据的相关性或强度")
知识点:
- 使用
sns.heatmap()创建热力图 - 使用
annot=True显示数值 - 使用
cmap参数设置颜色方案
4.8 高级图表:分组柱状图(Grouped Bar Chart)
分组柱状图用于比较多个类别在不同分组下的数值。
# 创建分组柱状图
fig, ax = plt.subplots(figsize=(10, 6))
# 按教育水平分组统计离职率
if 'Education_Level' in train.columns:
edu_attrition = train.groupby('Education_Level')['Attrition_rate'].mean().reset_index()
edu_attrition.columns = ['教育水平', '平均离职率']
x = np.arange(len(edu_attrition['教育水平']))
width = 0.6
bars = ax.bar(x, edu_attrition['平均离职率'], width,
label='平均离职率', color='#4ECDC4', edgecolor='black', linewidth=1.5)
ax.set_xlabel('教育水平', fontsize=12)
ax.set_ylabel('平均离职率', fontsize=12)
ax.set_title('不同教育水平的平均离职率(分组柱状图)', fontsize=14, fontweight='bold')
ax.set_xticks(x)
ax.set_xticklabels(edu_attrition['教育水平'])
ax.legend()
ax.grid(axis='y', alpha=0.3)
# 添加数值标签
for bar in bars:
height = bar.get_height()
ax.text(bar.get_x() + bar.get_width()/2., height + 0.01,
f'{height:.3f}', ha='center', va='bottom', fontsize=10)
plt.tight_layout()
plt.show()
print("💡 适用场景:比较多个类别在不同分组下的数值")
4.9 使用Seaborn创建高级图表
Seaborn提供了更美观和统计功能更强的图表。
# 使用Seaborn创建小提琴图(Violin Plot)
plt.figure(figsize=(10, 6))
ax = sns.violinplot(data=group_data, x=group_data.columns[0], y='离职率', palette='husl')
plt.title('离职率分布(小提琴图)', fontsize=14, fontweight='bold')
plt.xlabel(group_data.columns[0])
plt.ylabel('离职率')
plt.tight_layout()
plt.show()
print("💡 小提琴图结合了箱线图和核密度估计,展示数据分布更详细")
知识点:
- Seaborn提供了更美观的默认样式
- 小提琴图结合了箱线图和核密度估计,展示数据分布更详细
4.10 多子图展示
在一个图中展示多个子图,便于对比分析。
# 创建多子图
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
# 子图1:柱状图
axes[0, 0].bar(gender_data['性别'], gender_data['数量'], color='#4ECDC4')
axes[0, 0].set_title('柱状图', fontsize=12, fontweight='bold')
axes[0, 0].set_xlabel('性别')
axes[0, 0].set_ylabel('数量')
axes[0, 0].grid(axis='y', alpha=0.3)
# 子图2:折线图
axes[0, 1].plot(time_service_data['服务时长'], time_service_data['平均离职率'],
marker='o', color='#FF6B6B', markersize=4)
axes[0, 1].set_title('折线图', fontsize=12, fontweight='bold')
axes[0, 1].set_xlabel('服务时长')
axes[0, 1].set_ylabel('平均离职率')
axes[0, 1].grid(True, alpha=0.3)
# 子图3:散点图
axes[1, 0].scatter(continuous_data['年龄'], continuous_data['离职率'],
alpha=0.6, color='#45B7D1')
axes[1, 0].set_title('散点图', fontsize=12, fontweight='bold')
axes[1, 0].set_xlabel('年龄')
axes[1, 0].set_ylabel('离职率')
axes[1, 0].grid(True, alpha=0.3)
# 子图4:直方图
axes[1, 1].hist(continuous_data['年龄'], bins=30, edgecolor='black',
alpha=0.7, color='#FFA07A')
axes[1, 1].set_title('直方图', fontsize=12, fontweight='bold')
axes[1, 1].set_xlabel('年龄')
axes[1, 1].set_ylabel('频数')
axes[1, 1].grid(axis='y', alpha=0.3)
plt.suptitle('数据可视化示例集合', fontsize=16, fontweight='bold', y=0.995)
plt.tight_layout()
plt.show()
print("💡 多子图可以同时展示多个图表,便于对比分析")
知识点:
- 使用
plt.subplots()创建多子图 - 使用
axes对象操作各个子图 - 使用
plt.suptitle()添加总标题
阶段5:效果评估
3.5.1 图表优化技巧
展示如何优化图表的视觉效果,使其更加专业和美观。
# 创建一个优化后的图表示例
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 6))
# 左图:基础版本
ax1.bar(gender_data['性别'], gender_data['数量'], color='blue')
ax1.set_title('基础版本', fontsize=12)
ax1.set_xlabel('性别')
ax1.set_ylabel('数量')
# 右图:优化版本
colors = ['#FF6B6B', '#4ECDC4']
bars = ax2.bar(gender_data['性别'], gender_data['数量'], color=colors,
edgecolor='black', linewidth=1.5)
ax2.set_title('优化版本(添加颜色、边框、标签)', fontsize=12, fontweight='bold')
ax2.set_xlabel('性别', fontsize=11)
ax2.set_ylabel('数量', fontsize=11)
ax2.grid(axis='y', alpha=0.3, linestyle='--')
# 添加数值标签
for i, (bar, value) in enumerate(zip(bars, gender_data['数量'])):
height = bar.get_height()
ax2.text(bar.get_x() + bar.get_width()/2., height + 1,
f'{value}', ha='center', va='bottom', fontsize=10, fontweight='bold')
plt.suptitle('图表优化对比', fontsize=14, fontweight='bold')
plt.tight_layout()
plt.show()
print("=" * 60)
print("图表优化要点")
print("=" * 60)
print("1. ✅ 使用合适的颜色方案")
print("2. ✅ 添加清晰的标题和标签")
print("3. ✅ 添加数值标签(如需要)")
print("4. ✅ 使用网格线提高可读性")
print("5. ✅ 调整图表大小和布局")
print("6. ✅ 使用合适的字体大小和粗细")
3.5.2 图表选择指南
根据数据类型和目标,选择合适的图表类型。
# 创建图表选择指南
chart_selection_guide = {
"比较类别数值": ["柱状图", "条形图", "分组柱状图"],
"展示趋势": ["折线图", "面积图"],
"展示比例": ["饼图", "环形图", "堆叠柱状图"],
"展示分布": ["直方图", "箱线图", "小提琴图", "密度图"],
"展示关系": ["散点图", "气泡图", "热力图"],
"多变量分析": ["散点图矩阵", "平行坐标图"]
}
print("=" * 60)
print("图表选择指南")
print("=" * 60)
for purpose, charts in chart_selection_guide.items():
print(f"\n{purpose}:")
for chart in charts:
print(f" - {chart}")
print("\n" + "=" * 60)
print("💡 提示:选择合适的图表类型可以让数据更清晰地传达信息")
知识点:
- 根据数据类型和目标选择合适的图表类型
- 不同的图表类型适用于不同的场景
阶段6:部署应用
3.6.1 保存图表
将图表保存为图片文件,以便在报告中使用。
# 创建并保存一个示例图表
import os
# 确保输出目录存在
output_dir = 'visualization_output'
os.makedirs(output_dir, exist_ok=True)
# 创建一个高质量的图表
plt.figure(figsize=(12, 6))
plt.plot(time_service_data['服务时长'], time_service_data['平均离职率'],
marker='o', linewidth=2, label='平均离职率', color='#4ECDC4', markersize=8)
plt.xlabel('服务时长(年)', fontsize=12, fontweight='bold')
plt.ylabel('平均离职率', fontsize=12, fontweight='bold')
plt.title('服务时长与平均离职率趋势分析', fontsize=14, fontweight='bold', pad=20)
plt.legend(fontsize=11, loc='best')
plt.grid(True, alpha=0.3, linestyle='--')
# 保存为不同格式
png_file = os.path.join(output_dir, 'attrition_trend.png')
pdf_file = os.path.join(output_dir, 'attrition_trend.pdf')
plt.savefig(png_file, dpi=300, bbox_inches='tight', facecolor='white')
plt.savefig(pdf_file, bbox_inches='tight', facecolor='white')
plt.tight_layout()
plt.show()
print("=" * 60)
print("图表保存完成")
print("=" * 60)
print(f"✅ PNG格式: {png_file}")
print(f"✅ PDF格式: {pdf_file}")
print("\n💡 提示:")
print(" - PNG格式适合网页和演示")
print(" - PDF格式适合打印和高质量文档")
print(" - 使用dpi=300可以获得高质量图片")
知识点:
- 使用
plt.savefig()保存图表 - 使用
dpi=300获得高质量图片 - 使用
bbox_inches='tight'去除多余的空白
4. 关键技术点总结
4.1 基础图表类型
- 柱状图:比较不同类别的数值大小
- 折线图:展示数据随时间的变化趋势
- 散点图:展示两个变量之间的关系
- 饼图:展示各部分占整体的比例
4.2 统计图表类型
- 直方图:展示数据的分布情况
- 箱线图:展示数据的分布、中位数、四分位数和异常值
- 小提琴图:结合箱线图和核密度估计,展示数据分布更详细
4.3 高级图表类型
- 热力图:展示矩阵数据的相关性或强度
- 分组柱状图:比较多个类别在不同分组下的数值
- 多子图:在一个图中展示多个图表,便于对比分析
4.4 图表优化技巧
- 颜色方案:使用合适的颜色方案,提高视觉效果
- 标题和标签:添加清晰的标题和标签,提高可读性
- 数值标签:在需要时添加数值标签,提供具体数值
- 网格线:使用网格线提高可读性
- 字体大小:使用合适的字体大小和粗细
4.5 图表选择指南
- 比较类别数值:柱状图、条形图、分组柱状图
- 展示趋势:折线图、面积图
- 展示比例:饼图、环形图、堆叠柱状图
- 展示分布:直方图、箱线图、小提琴图、密度图
- 展示关系:散点图、气泡图、热力图
- 多变量分析:散点图矩阵、平行坐标图
5. 项目总结与扩展
5.1 项目成果
✅ 项目完成情况:
- ✅ 需求界定:明确了数据可视化的目标和应用场景
- ✅ 数据获取:加载了员工离职数据集
- ✅ 数据分析:了解了不同数据类型的特征
- ✅ 模型构建:创建了10+种不同类型的图表
- ✅ 效果评估:学习了图表优化技巧和选择指南
- ✅ 部署应用:掌握了图表保存和函数封装方法
5.2 主要发现
- 图表类型选择:根据数据类型和目标选择合适的图表类型非常重要
- 视觉效果优化:颜色、标签、网格等细节可以显著提升图表质量
- 工具选择:Matplotlib适合基础图表,Seaborn适合统计图表
- 可复用性:创建可视化函数可以提高工作效率
5.3 后续改进方向
-
高级可视化:
- 交互式图表(Plotly、Bokeh)
- 3D可视化
- 动画图表
-
专业报告:
- 创建完整的可视化报告
- 使用模板和主题
- 自动化报告生成
-
实际应用:
- 结合真实数据集
- 创建仪表板(Dashboard)
- 实时数据可视化
-
学习扩展:
- 学习更多图表类型
- 掌握配色理论
- 了解数据故事讲述
6. 参考资料
-
技术文档:
- Matplotlib官方文档:https://matplotlib.org/
- Seaborn官方文档:https://seaborn.pydata.org/
- Pandas官方文档:https://pandas.pydata.org/
-
相关教程:
- Python数据可视化最佳实践
- 图表选择指南
结语
本项目完整展示了从需求界定到图表保存的数据可视化流程,通过创建10+种不同类型的图表,我们了解了各种图表类型的适用场景和优化技巧。在实际应用中,可以根据具体需求选择合适的图表类型,并通过优化技巧提升图表的专业性和美观度。
希望本文能够帮助读者掌握Python数据可视化的基础技能,并为实际项目提供参考。如有问题或建议,欢迎交流讨论!
作者 :Testopia
日期 :2026年2月
标签:#数据可视化 #Matplotlib #Seaborn #Python #数据分析 #AI项目周期