第15章:Pandas数据分析
🎯 学习目标
通过本章学习,你将掌握Python数据分析利器Pandas的核心功能,学会处理真实世界的数据分析任务,为成为数据分析师打下坚实基础。
📖 本章导读
在现代数据驱动的世界中,数据分析能力已成为各行各业的核心技能。无论是商业决策、科学研究,还是日常工作,我们都需要从海量数据中提取有价值的信息。
为什么学习Pandas?
- 🏭 数据工厂的管理者:Pandas就像一个智能化的数据工厂,能够高效处理各种"原料"(数据)
- 📊 数据科学的基石:90%的数据科学工作都离不开Pandas
- 🚀 职场竞争力:掌握Pandas是数据分析岗位的必备技能
- 🎯 解决实际问题:从学生成绩分析到企业销售报表,无所不能
本章知识地图:
15.1 Pandas基础与数据结构
🏭 数据工厂的原料仓库
想象一下,你是一家现代化数据工厂的管理者。工厂里有两种主要的原料仓库:
- Series仓库:专门存储单一类型的产品,如"所有学生的数学成绩"
- DataFrame仓库:存储多种相关产品,如"学生信息表(姓名、年龄、各科成绩)"
15.1.1 Pandas简介与环境准备
Pandas(Panel Data Analysis)是基于NumPy构建的数据分析库,提供了高性能、易用的数据结构和数据分析工具。
# 安装Pandas(如果还未安装)# pip install pandas matplotlib seabornimport pandas as pdimport numpy as npimport matplotlib.pyplot as pltimport seaborn as sns# 设置中文显示plt.rcParams['font.sans-serif'] = ['SimHei']plt.rcParams['axes.unicode_minus'] = False# 设置显示选项pd.set_option('display.max_columns', None)pd.set_option('display.width', None)pd.set_option('display.max_colwidth', 20)print("Pandas版本:", pd.__version__)print("数据工厂已准备就绪!🏭")
15.1.2 Series:单一产品线的数据容器
Series是Pandas中的一维数据结构,类似于带标签的数组。
# === Series创建方法 ===# 方法1:从列表创建students_math_scores = pd.Series([85, 92, 78, 96, 88],name='数学成绩')print("📊 学生数学成绩:")print(students_math_scores)print()# 方法2:从字典创建(自动生成索引)student_scores = pd.Series({'张三': 85,'李四': 92,'王五': 78,'赵六': 96,'钱七': 88}, name='数学成绩')print("📋 带姓名的成绩单:")print(student_scores)print()# 方法3:指定索引ages = pd.Series([18, 19, 18, 20, 19],index=['张三', '李四', '王五', '赵六', '钱七'],name='年龄')print("👥 学生年龄信息:")print(ages)print()# === Series基本属性 ===print("=== Series基本信息 ===")print(f"数据类型: {student_scores.dtype}")print(f"数据长度: {len(student_scores)}")print(f"索引: {student_scores.index.tolist()}")print(f"数值: {student_scores.values}")print(f"名称: {student_scores.name}")
Series的核心操作
# === 数据访问 ===print("=== 数据访问方式 ===")# 按索引访问print(f"张三的成绩: {student_scores['张三']}")print(f"李四的成绩: {student_scores.loc['李四']}")# 按位置访问print(f"第一个学生成绩: {student_scores.iloc[0]}")print(f"前三个学生成绩:\n{student_scores.iloc[:3]}")# 条件筛选high_scores = student_scores[student_scores >= 90]print(f"\n优秀学生(≥90分):\n{high_scores}")# === 数据修改 ===print("\n=== 数据修改 ===")student_scores_copy = student_scores.copy()student_scores_copy['张三'] = 90 # 修改单个值print(f"张三成绩修改后: {student_scores_copy['张三']}")# 批量修改student_scores_copy[student_scores_copy < 80] += 5 # 低分加5分print(f"低分提升后:\n{student_scores_copy}")# === 数学运算 ===print("\n=== 数学运算 ===")print(f"平均分: {student_scores.mean():.2f}")print(f"最高分: {student_scores.max()}")print(f"最低分: {student_scores.min()}")print(f"标准差: {student_scores.std():.2f}")# 成绩加权(期末成绩占70%)final_scores = student_scores * 0.7print(f"\n期末成绩(70%权重):\n{final_scores}")
15.1.3 DataFrame:多产品线的数据管理系统
DataFrame是Pandas的核心数据结构,可以理解为带标签的二维表格。
# === DataFrame创建方法 ===# 方法1:从字典创建student_data = {'姓名': ['张三', '李四', '王五', '赵六', '钱七'],'年龄': [18, 19, 18, 20, 19],'性别': ['男', '女', '男', '女', '男'],'数学': [85, 92, 78, 96, 88],'语文': [88, 85, 92, 89, 87],'英语': [82, 94, 85, 93, 90]}df_students = pd.DataFrame(student_data)print("📊 学生信息表:")print(df_students)print()# 方法2:从嵌套列表创建data_matrix = [['张三', 18, '男', 85, 88, 82],['李四', 19, '女', 92, 85, 94],['王五', 18, '男', 78, 92, 85],['赵六', 20, '女', 96, 89, 93],['钱七', 19, '男', 88, 87, 90]]df_from_list = pd.DataFrame(data_matrix,columns=['姓名', '年龄', '性别', '数学', '语文', '英语'])print("📋 从列表创建的DataFrame:")print(df_from_list.head(3)) # 显示前3行print()# === DataFrame基本信息 ===print("=== DataFrame基本信息 ===")print(f"形状 (行数, 列数): {df_students.shape}")print(f"列名: {df_students.columns.tolist()}")print(f"索引: {df_students.index.tolist()}")print(f"数据类型:\n{df_students.dtypes}")print()# 详细信息print("=== 详细信息 ===")print(df_students.info())print()# 描述性统计print("=== 数值列描述性统计 ===")print(df_students.describe())
DataFrame的数据访问
# === 列操作 ===print("=== 列操作 ===")# 选择单列(返回Series)math_scores = df_students['数学']print(f"数学成绩列:\n{math_scores}")print(f"类型: {type(math_scores)}")print()# 选择多列(返回DataFrame)score_columns = df_students[['姓名', '数学', '语文', '英语']]print("成绩相关列:")print(score_columns)print()# === 行操作 ===print("=== 行操作 ===")# 按位置选择行first_student = df_students.iloc[0] # 第一行print(f"第一个学生信息:\n{first_student}")print()# 按索引选择行student_info = df_students.loc[0] # 索引为0的行print(f"索引0的学生信息:\n{student_info}")print()# 选择多行first_three = df_students.iloc[:3] # 前三行print("前三个学生:")print(first_three)print()# === 条件筛选 ===print("=== 条件筛选 ===")# 单条件筛选high_math = df_students[df_students['数学'] >= 90]print("数学成绩优秀的学生:")print(high_math)print()# 多条件筛选excellent_students = df_students[(df_students['数学'] >= 85) &(df_students['语文'] >= 85)]print("数学和语文都优秀的学生:")print(excellent_students)print()# 字符串条件male_students = df_students[df_students['性别'] == '男']print("男学生信息:")print(male_students)
15.1.4 索引系统:仓库的货架编号
索引是Pandas的核心概念,就像仓库中的货架编号系统。
# === 设置索引 ===print("=== 索引操作 ===")# 将姓名设为索引df_indexed = df_students.set_index('姓名')print("以姓名为索引的DataFrame:")print(df_indexed)print()# 重置索引df_reset = df_indexed.reset_index()print("重置索引后:")print(df_reset.head(3))print()# === 多层索引 ===print("=== 多层索引示例 ===")# 创建多层索引数据multi_data = {'成绩': [85, 88, 82, 92, 85, 94, 78, 92, 85],'学期': ['第一学期', '第一学期', '第一学期', '第二学期', '第二学期', '第二学期', '第三学期', '第三学期', '第三学期']}multi_index = pd.MultiIndex.from_tuples([('张三', '数学'), ('张三', '语文'), ('张三', '英语'),('李四', '数学'), ('李四', '语文'), ('李四', '英语'),('王五', '数学'), ('王五', '语文'), ('王五', '英语')], names=['学生', '科目'])df_multi = pd.DataFrame(multi_data, index=multi_index)print("多层索引DataFrame:")print(df_multi)print()# 多层索引访问print("张三的所有成绩:")print(df_multi.loc['张三'])print()print("所有学生的数学成绩:")print(df_multi.loc[(slice(None), '数学'), :])
🎯 实践项目:学生成绩管理系统
让我们创建一个完整的学生成绩管理系统,展示Pandas基础功能的综合应用。
class StudentGradeManager:"""学生成绩管理系统这个系统模拟了一个数据工厂的完整流程:- 原料入库:录入学生信息和成绩- 质量检查:数据验证和清洗- 生产加工:成绩计算和统计- 产品包装:报表生成和可视化"""def __init__(self):self.students_df = pd.DataFrame()self.subjects = ['数学', '语文', '英语', '物理', '化学']def add_student(self, name, age, gender, scores):"""添加学生信息"""if len(scores) != len(self.subjects):raise ValueError(f"成绩数量必须为{len(self.subjects)}个")student_data = {'姓名': name,'年龄': age,'性别': gender}# 添加各科成绩for subject, score in zip(self.subjects, scores):student_data[subject] = score# 转换为DataFrame并添加到主表new_student = pd.DataFrame([student_data])self.students_df = pd.concat([self.students_df, new_student],ignore_index=True)print(f"✅ 学生 {name} 信息已录入")def batch_add_students(self, students_list):"""批量添加学生"""for student in students_list:self.add_student(*student)def calculate_total_average(self):"""计算总分和平均分"""# 计算总分self.students_df['总分'] = self.students_df[self.subjects].sum(axis=1)# 计算平均分self.students_df['平均分'] = self.students_df[self.subjects].mean(axis=1)print("✅ 总分和平均分计算完成")def get_rank(self):"""计算排名"""self.students_df['排名'] = self.students_df['总分'].rank(method='min', ascending=False).astype(int)print("✅ 排名计算完成")def get_statistics(self):"""获取统计信息"""stats = {'学生总数': len(self.students_df),'男生人数': len(self.students_df[self.students_df['性别'] == '男']),'女生人数': len(self.students_df[self.students_df['性别'] == '女']),'平均年龄': self.students_df['年龄'].mean(),'总分最高': self.students_df['总分'].max(),'总分最低': self.students_df['总分'].min(),'班级平均分': self.students_df['平均分'].mean()}return statsdef get_subject_analysis(self):"""各科成绩分析"""subject_stats = {}for subject in self.subjects:subject_stats[subject] = {'平均分': self.students_df[subject].mean(),'最高分': self.students_df[subject].max(),'最低分': self.students_df[subject].min(),'标准差': self.students_df[subject].std(),'及格率': (self.students_df[subject] >= 60).mean() * 100}return subject_statsdef find_excellent_students(self, threshold=85):"""查找优秀学生(平均分超过阈值)"""excellent = self.students_df[self.students_df['平均分'] >= threshold].sort_values('平均分', ascending=False)return excellentdef generate_report(self):"""生成完整报告"""print("=" * 50)print("📊 学生成绩管理系统报告")print("=" * 50)# 基本统计stats = self.get_statistics()print("\n📈 基本统计信息:")for key, value in stats.items():if isinstance(value, float):print(f" {key}: {value:.2f}")else:print(f" {key}: {value}")# 各科分析print("\n📚 各科成绩分析:")subject_stats = self.get_subject_analysis()for subject, stats in subject_stats.items():print(f"\n {subject}:")for key, value in stats.items():print(f" {key}: {value:.2f}")# 优秀学生print("\n🏆 优秀学生名单 (平均分≥85):")excellent = self.find_excellent_students()if not excellent.empty:print(excellent[['姓名', '平均分', '排名']].to_string(index=False))else:print(" 暂无优秀学生")# 完整成绩单print("\n📋 完整成绩单:")display_df = self.students_df.sort_values('排名')print(display_df.to_string(index=False))# === 使用示例 ===if __name__ == "__main__":# 创建 成绩管理系统grade_manager = StudentGradeManager()# 示例学生数据students_data = [('张三', 18, '男', [85, 88, 82, 90, 87]),('李四', 19, '女', [92, 85, 94, 88, 91]),('王五', 18, '男', [78, 92, 85, 82, 79]),('赵六', 20, '女', [96, 89, 93, 95, 94]),('钱七', 19, '男', [88, 87, 90, 85, 89]),('孙八', 18, '女', [83, 91, 87, 89, 85]),('周九', 19, '男', [90, 84, 88, 92, 86]),('吴十', 18, '女', [87, 93, 91, 88, 92])]# 批量添加学生print("🏭 数据 工厂开始运作...")grade_manager.batch_add_students(students_data)# 计算总分和平均分grade_manager.calculate_total_average()# 计算排名grade_manager.get_rank()# 生成报告grade_manager.generate_report()print("\n🎉 学生成绩管理系统演示完成!")
💡 核心概念总结
- Series:一维标签数组,适合存储单一类型的数据
- DataFrame:二维标签表格,Pandas的核心数据结构
- Index:行和列的标签系统,支持快速数据访问
- 数据访问:支持标签访问(.loc)和位置访问(.iloc)
- 条件筛选:使用布尔索引进行数据过滤
通过"数据工厂"的比喻,我们了解了Pandas的基本数据结构。接下来,让我们学习如何将各种"原料"(数据文件)导入到我们的工厂中。