Python 从入门到实战(十):Pandas 数据处理(高效搞定表格数据的 “瑞士军刀”)

文章目录

    • [一、为什么需要 Pandas?先看`csv`模块的痛点](#一、为什么需要 Pandas?先看csv模块的痛点)
    • [二、Pandas 基础:安装与核心数据结构](#二、Pandas 基础:安装与核心数据结构)
      • [1. 安装 Pandas(新手必看)](#1. 安装 Pandas(新手必看))
      • [2. 核心结构 1:Series(一维数据,像 "带标签的列表")](#2. 核心结构 1:Series(一维数据,像 “带标签的列表”))
      • [3. 核心结构 2:DataFrame(二维表格,像 "Excel 工作表")](#3. 核心结构 2:DataFrame(二维表格,像 “Excel 工作表”))
    • [三、Pandas 实战 1:数据读取与查看(衔接上一篇数据)](#三、Pandas 实战 1:数据读取与查看(衔接上一篇数据))
    • [四、Pandas 实战 2:数据筛选与修改(核心操作)](#四、Pandas 实战 2:数据筛选与修改(核心操作))
      • [1. 数据筛选(条件筛选 + 列选择)](#1. 数据筛选(条件筛选 + 列选择))
        • [示例 1:筛选 "数学成绩> 85 的学生"](#示例 1:筛选 “数学成绩> 85 的学生”)
        • 运行结果
        • [示例 2:筛选 "15 岁学生的英语成绩"](#示例 2:筛选 “15 岁学生的英语成绩”)
        • 运行结果
        • 筛选技巧
      • [2. 数据修改(修改值 + 添加新列)](#2. 数据修改(修改值 + 添加新列))
        • [示例 1:修改错误成绩(比如小刚的英语成绩从 80 改为 82)](#示例 1:修改错误成绩(比如小刚的英语成绩从 80 改为 82))
        • 运行结果
        • [示例 2:添加新列(计算每个学生的 "成绩等级")](#示例 2:添加新列(计算每个学生的 “成绩等级”))
        • 运行结果
    • [五、Pandas 实战 3:数据清洗与统计(处理实际问题)](#五、Pandas 实战 3:数据清洗与统计(处理实际问题))
      • [1. 数据清洗(处理缺失值、重复值)](#1. 数据清洗(处理缺失值、重复值))
      • [2. 数据统计与聚合(分组统计)](#2. 数据统计与聚合(分组统计))
        • [示例 1:计算各科平均分、最高分](#示例 1:计算各科平均分、最高分)
        • 运行结果
        • [示例 2:按姓名分组,计算每个学生的总分和平均分](#示例 2:按姓名分组,计算每个学生的总分和平均分)
        • 运行结果
    • [六、综合实操:学生成绩分析系统(Pandas 版)](#六、综合实操:学生成绩分析系统(Pandas 版))
    • [七、新手必踩的 5 个坑:避坑指南](#七、新手必踩的 5 个坑:避坑指南)
      • [坑 1:数据类型不匹配(比如成绩是字符串)](#坑 1:数据类型不匹配(比如成绩是字符串))
      • [坑 2:用`=`修改数据不生效(忘记`inplace=True`)](#坑 2:用=修改数据不生效(忘记inplace=True))
      • [坑 3:筛选多条件时用`and/or`而非`&/|`](#坑 3:筛选多条件时用and/or而非&/|)
      • [坑 4:读取 Excel 时缺少依赖(openpyxl/xlrd)](#坑 4:读取 Excel 时缺少依赖(openpyxl/xlrd))
      • [坑 5:`loc`与`iloc`混淆(按索引 vs 按位置)](#坑 5:lociloc混淆(按索引 vs 按位置))
    • 八、小结与下一篇预告

欢迎回到「Python 从入门到实战」系列专栏。上一篇咱们用 csv模块实现了学生数据的持久化,但在实际处理中发现了不少麻烦:比如想筛选 "数学成绩大于 85 的学生",需要手动循环遍历;想计算 "各年龄段的平均分",得自己分组统计;遇到缺失数据(比如某学生漏填了成绩),还要写额外代码处理。这些操作用 csv模块不仅繁琐,还容易出错。

今天咱们要学 Python 数据处理的 "王牌工具"------Pandas 库 。它就像一把 "瑞士军刀",能轻松搞定表格数据的读取、筛选、清洗、统计等操作,一行代码就能完成csv模块几十行代码的工作。咱们会从基础的 "安装与核心结构" 入手,再结合上一篇的学生数据,实战演示 "读取数据→查看筛选→清洗统计→保存结果" 的完整流程,让你彻底摆脱手动处理表格数据的烦恼。

一、为什么需要 Pandas?先看csv模块的痛点

在学 Pandas 之前,先回顾上一篇用csv模块处理学生数据的场景,感受它的局限性:

python

运行

python 复制代码
# 用csv模块筛选数学成绩>85的学生(繁琐)
import csv

passed_students = []
with open("students_data.csv", mode='r', encoding='utf-8') as file:
    reader = csv.DictReader(file)
    for row in reader:
        # 手动转换数据类型,处理可能的错误
        try:
            math_score = int(row["course_score"])
            if row["course_name"] == "数学" and math_score > 85:
                passed_students.append(row["name"])
        except ValueError:
            print(f"数据错误:{row}")

print("数学成绩>85的学生:", passed_students)

这段代码要做的只是 "筛选数学成绩大于 85 的学生",却需要写循环、异常处理、条件判断,步骤繁琐。而用 Pandas,只需一行代码:

python

运行

python 复制代码
import pandas as pd

# 一行代码完成筛选
df = pd.read_csv("students_data.csv")
passed_students = df[(df["course_name"] == "数学") & (df["course_score"] > 85)]["name"].tolist()
print("数学成绩>85的学生:", passed_students)

效率差距一目了然!Pandas 的核心优势在于:

  1. 简化代码:用内置方法替代手动循环,一行代码搞定筛选、统计;
  2. 自动处理:自动识别数据类型、处理表头,减少手动转换;
  3. 强大功能:支持缺失值处理、数据聚合、多表合并等复杂操作;
  4. 兼容广泛:轻松读取 CSV、Excel、JSON 等多种格式文件。

二、Pandas 基础:安装与核心数据结构

Pandas 是第三方库(非 Python 自带),需要先安装才能使用。咱们先搞定安装,再学习它的两个核心数据结构 ------Series(一维数据)和DataFrame(二维表格)。

1. 安装 Pandas(新手必看)

打开终端 / 命令提示符,输入以下命令安装:

bash

运行

bash 复制代码
# 基础安装(支持CSV等格式)
pip install pandas

# 如需读取Excel文件,额外安装依赖(必装)
pip install openpyxl  # 读取.xlsx格式
pip install xlrd       # 读取.xls格式(旧版Excel)

安装完成后,在 Python 中导入 Pandas,习惯用pd作为别名(行业通用):

python

运行

python 复制代码
import pandas as pd

2. 核心结构 1:Series(一维数据,像 "带标签的列表")

Series是 Pandas 的一维数据结构,类似 Python 列表,但每个元素都有一个 "索引(index)",可以是数字、字符串等。比如用它存储 "学生姓名" 或 "数学成绩"。

示例:创建并操作 Series

python

运行

python 复制代码
import pandas as pd

# 1. 从列表创建Series(默认索引是0,1,2...)
math_scores = pd.Series([85, 95, 78, 92], name="数学成绩")
print("默认索引的Series:")
print(math_scores)
print("数据类型:", type(math_scores))  # <class 'pandas.core.series.Series'>

# 2. 自定义索引(比如用学生姓名)
math_scores_idx = pd.Series(
    [85, 95, 78, 92],
    index=["小明", "小红", "小刚", "小丽"],  # 自定义索引(字符串)
    name="数学成绩"
)
print("\n自定义索引的Series:")
print(math_scores_idx)

# 3. 访问Series数据(类似字典/列表)
print("\n访问小红的数学成绩:", math_scores_idx["小红"])  # 用索引访问
print("访问前3个成绩:", math_scores_idx.head(3))       # 前3个元素
print("成绩大于85的学生:")
print(math_scores_idx[math_scores_idx > 85])  # 条件筛选
运行结果

plaintext

plaintext 复制代码
默认索引的Series:
0    85
1    95
2    78
3    92
Name: 数学成绩, dtype: int64
数据类型: <class 'pandas.core.series.Series'>

自定义索引的Series:
小明    85
小红    95
小刚    78
小丽    92
Name: 数学成绩, dtype: int64

访问小红的数学成绩: 95
访问前3个成绩: 小明    85
小红    95
小刚    78
Name: 数学成绩, dtype: int64
成绩大于85的学生:
小红    95
小丽    92
Name: 数学成绩, dtype: int64
核心特点
  • 有 "索引" 和 "值" 两部分,索引可自定义;
  • 支持条件筛选、切片(head()/tail())等操作;
  • 自动识别数据类型(如dtype: int64表示整数)。

3. 核心结构 2:DataFrame(二维表格,像 "Excel 工作表")

DataFrame是 Pandas 的二维数据结构,相当于一张 Excel 表格,有 "行索引" 和 "列名",是处理表格数据的核心。比如用它存储完整的学生数据(姓名、年龄、课程、成绩)。

示例:创建并操作 DataFrame

python

运行

python 复制代码
import pandas as pd

# 1. 从字典创建DataFrame(键=列名,值=列数据)
student_data = {
    "name": ["小明", "小红", "小刚", "小丽"],
    "age": [15, 14, 15, 14],
    "course_name": ["数学", "数学", "数学", "数学"],
    "course_score": [85, 95, 78, 92]
}
df = pd.DataFrame(student_data)

print("学生DataFrame(默认行索引):")
print(df)
print("数据类型:", type(df))  # <class 'pandas.core.frame.DataFrame'>

# 2. 自定义行索引(比如用学生ID)
df_idx = pd.DataFrame(
    student_data,
    index=["S001", "S002", "S003", "S004"]  # 自定义行索引(学生ID)
)
print("\n自定义行索引的DataFrame:")
print(df_idx)

# 3. 访问列数据(用列名,返回Series)
print("\n访问'name'列:")
print(df["name"])  # 或df.name(列名无空格时可用)

# 4. 访问行数据(用loc[]按索引,iloc[]按位置)
print("\n访问S002的信息(loc按索引):")
print(df_idx.loc["S002"])
print("\n访问第2行信息(iloc按位置,从0开始):")
print(df_idx.iloc[1])
运行结果

plaintext

plaintext 复制代码
学生DataFrame(默认行索引):
  name  age course_name  course_score
0   小明   15         数学            85
1   小红   14         数学            95
2   小刚   15         数学            78
3   小丽   14         数学            92
数据类型: <class 'pandas.core.frame.DataFrame'>

自定义行索引的DataFrame:
     name  age course_name  course_score
S001   小明   15         数学            85
S002   小红   14         数学            95
S003   小刚   15         数学            78
S004   小丽   14         数学            92

访问'name'列:
0    小明
1    小红
2    小刚
3    小丽
Name: name, dtype: object

访问S002的信息(loc按索引):
name            小红
age             14
course_name     数学
course_score    95
Name: S002, dtype: object

访问第2行信息(iloc按位置):
name            小红
age             14
course_name     数学
course_score    95
Name: S002, dtype: object
核心特点
  • 有 "行索引" 和 "列名",结构清晰,像 Excel 表格;
  • 访问列用df["列名"],访问行用loc[](按索引)或iloc[](按位置);
  • 支持批量操作(筛选、修改、统计),效率极高。

三、Pandas 实战 1:数据读取与查看(衔接上一篇数据)

上一篇我们生成了students_data.csv文件(学生课程数据),现在用 Pandas 读取它,对比csv模块的繁琐,感受 Pandas 的简洁。

1. 读取 CSV 文件(一行代码)

python

运行

python 复制代码
import pandas as pd

# 读取CSV文件(自动识别表头,处理编码)
df = pd.read_csv(
    "students_data.csv",  # 文件路径
    encoding="utf-8",     # 解决中文乱码
    dtype={"course_score": int}  # 指定列的数据类型(避免成绩为字符串)
)

print("读取的学生数据:")
print(df)
假设students_data.csv内容

plaintext

plaintext 复制代码
name,age,course_name,course_score
小明,15,数学,85
小明,15,英语,92
小红,14,数学,95
小红,14,英语,88
小刚,15,数学,78
小刚,15,英语,80
运行结果

plaintext

plaintext 复制代码
读取的学生数据:
  name  age course_name  course_score
0   小明   15         数学            85
1   小明   15         英语            92
2   小红   14         数学            95
3   小红   14         英语            88
4   小刚   15         数学            78
5   小刚   15         英语            80

对比csv模块 :不用手动创建reader、循环读取、转换数据类型,Pandas 一行代码全搞定!

2. 读取 Excel 文件(实际应用常用)

除了 CSV,Excel(.xlsx/.xls)是更常用的表格格式,Pandas 也能轻松读取:

python

运行

python 复制代码
import pandas as pd

# 读取Excel文件(需要先安装openpyxl)
df_excel = pd.read_excel(
    "students_data.xlsx",  # Excel文件路径
    sheet_name="Sheet1",   # 工作表名称(默认Sheet1)
    encoding="utf-8",
    dtype={"course_score": int}
)

print("读取的Excel数据:")
print(df_excel)

注意 :如果报错 "Missing optional dependency 'openpyxl'",请执行pip install openpyxl安装依赖。

3. 快速查看数据(避免手动循环)

读取数据后,通常需要快速了解数据的基本情况(比如有多少行、列,数据类型,是否有缺失),Pandas 提供了 4 个常用方法:

示例:查看学生数据基本信息

python

运行

python 复制代码
import pandas as pd

df = pd.read_csv("students_data.csv", encoding="utf-8", dtype={"course_score": int})

# 1. head(n):查看前n行(默认5行)
print("前3行数据:")
print(df.head(3))

# 2. info():查看数据基本信息(行数、列数、数据类型、缺失值)
print("\n数据基本信息:")
print(df.info())

# 3. describe():查看数值列的统计信息(均值、标准差、最值等)
print("\n数值列统计(age和course_score):")
print(df.describe())

# 4. value_counts():统计某列的唯一值数量(比如各课程的数量)
print("\n各课程的学生数量:")
print(df["course_name"].value_counts())
运行结果

plaintext

plaintext 复制代码
前3行数据:
  name  age course_name  course_score
0   小明   15         数学            85
1   小明   15         英语            92
2   小红   14         数学            95

数据基本信息:
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 6 entries, 0 to 5
Data columns (total 4 columns):
 #   Column         Non-Null Count  Dtype
---  ------         --------------  -----
 0   name           6 non-null      object
 1   age            6 non-null      int64
 2   course_name    6 non-null      object
 3   course_score   6 non-null      int64
dtypes: int64(2), object(2)
memory usage: 320.0+ bytes

数值列统计(age和course_score):
        age  course_score
count   6.000000        6.000000
mean   14.666667       86.333333
std     0.516398        6.658328
min    14.000000       78.000000
25%    14.000000       80.000000
50%    15.000000       86.500000
75%    15.000000       90.500000
max    15.000000       95.000000

各课程的学生数量:
course_name
数学    3
英语    3
Name: count, dtype: int64

价值:不用写任何循环,就能快速掌握数据全貌 ------ 比如有 6 行数据、无缺失值、学生年龄集中在 14-15 岁、数学和英语各 3 个学生。

四、Pandas 实战 2:数据筛选与修改(核心操作)

处理数据时,最常用的需求是 "筛选特定数据"(比如成绩好的学生)和 "修改数据"(比如修正错误成绩)。Pandas 的操作比csv模块简洁 10 倍!

1. 数据筛选(条件筛选 + 列选择)

示例 1:筛选 "数学成绩> 85 的学生"

python

运行

python 复制代码
import pandas as pd

df = pd.read_csv("students_data.csv", encoding="utf-8", dtype={"course_score": int})

# 1. 条件筛选:数学成绩>85
math_high = df[(df["course_name"] == "数学") & (df["course_score"] > 85)]
print("数学成绩>85的学生:")
print(math_high)

# 2. 只显示需要的列(name、course_score)
math_high_simple = math_high[["name", "course_score"]]
print("\n简化显示(只看姓名和成绩):")
print(math_high_simple)
运行结果

plaintext

plaintext 复制代码
数学成绩>85的学生:
  name  age course_name  course_score
2   小红   14         数学            95

简化显示(只看姓名和成绩):
  name  course_score
2   小红            95
示例 2:筛选 "15 岁学生的英语成绩"

python

运行

python 复制代码
# 条件:age==15 且 course_name=="英语"
english_15 = df[(df["age"] == 15) & (df["course_name"] == "英语")]
print("15岁学生的英语成绩:")
print(english_15[["name", "course_score"]])
运行结果

plaintext

plaintext 复制代码
15岁学生的英语成绩:
  name  course_score
1   小明            92
5   小刚            80
筛选技巧
  • 多条件用&(且)、|(或)连接,每个条件加括号;
  • 选择列用df[["列1", "列2"]](双括号返回 DataFrame,单括号返回 Series)。

2. 数据修改(修改值 + 添加新列)

示例 1:修改错误成绩(比如小刚的英语成绩从 80 改为 82)

python

运行

python 复制代码
import pandas as pd

df = pd.read_csv("students_data.csv", encoding="utf-8", dtype={"course_score": int})

# 1. 定位并修改:小刚的英语成绩
# 条件:name=="小刚" 且 course_name=="英语"
df.loc[(df["name"] == "小刚") & (df["course_name"] == "英语"), "course_score"] = 82

print("修改后的成绩:")
print(df[df["name"] == "小刚"])
运行结果

plaintext

plaintext 复制代码
修改后的成绩:
  name  age course_name  course_score
4   小刚   15         数学            78
5   小刚   15         英语            82  # 已从80改为82
示例 2:添加新列(计算每个学生的 "成绩等级")

python

运行

python 复制代码
# 定义等级规则:90+为A,80-89为B,<80为C
def get_grade(score):
    if score >= 90:
        return "A"
    elif score >= 80:
        return "B"
    else:
        return "C"

# 应用函数,添加"grade"列
df["grade"] = df["course_score"].apply(get_grade)

print("添加等级后的完整数据:")
print(df)
运行结果

plaintext

plaintext 复制代码
添加等级后的完整数据:
  name  age course_name  course_score grade
0   小明   15         数学            85     B
1   小明   15         英语            92     A
2   小红   14         数学            95     A
3   小红   14         英语            88     B
4   小刚   15         数学            78     C
5   小刚   15         英语            82     B

技巧 :用df["列名"].apply(函数)可以批量对列数据应用自定义逻辑,比循环高效得多。

五、Pandas 实战 3:数据清洗与统计(处理实际问题)

实际数据中常存在 "缺失值"(比如某学生漏填年龄)、"重复数据"(比如重复录入),需要先清洗再统计。Pandas 提供了专门的方法处理这些问题。

1. 数据清洗(处理缺失值、重复值)

示例:处理含缺失值的学生数据

假设students_data_missing.csv有缺失值(小明的年龄缺失,小红的英语成绩缺失):

csv

csv 复制代码
name,age,course_name,course_score
小明,,数学,85
小明,15,英语,92
小红,14,数学,95
小红,14,英语,
小刚,15,数学,78
小刚,15,英语,82
清洗步骤

python

运行

python 复制代码
import pandas as pd

# 读取含缺失值的数据
df = pd.read_csv("students_data_missing.csv", encoding="utf-8")

print("原始数据(含缺失值):")
print(df)

# 1. 查看缺失值情况(info()或isnull().sum())
print("\n各列缺失值数量:")
print(df.isnull().sum())  # 统计每列缺失值

# 2. 处理缺失值(两种常见方式)
# 方式1:填充缺失值(年龄用均值,成绩用0)
df["age"].fillna(df["age"].mean(), inplace=True)  # 年龄缺失用均值填充
df["course_score"].fillna(0, inplace=True)       # 成绩缺失用0填充

# 方式2:删除缺失值(如果缺失行较少,用df.dropna(inplace=True))

# 3. 转换数据类型(填充后年龄可能为浮点数,转为整数)
df["age"] = df["age"].astype(int)
df["course_score"] = df["course_score"].astype(int)

print("\n清洗后的数据:")
print(df)
运行结果

plaintext

plaintext 复制代码
原始数据(含缺失值):
  name   age course_name  course_score
0   小明   NaN         数学          85.0
1   小明  15.0         英语          92.0
2   小红  14.0         数学          95.0
3   小红  14.0         英语           NaN
4   小刚  15.0         数学          78.0
5   小刚  15.0         英语          82.0

各列缺失值数量:
name             0
age              1
course_name      0
course_score     1
dtype: int64

清洗后的数据:
  name  age course_name  course_score
0   小明   14         数学            85  # 年龄用均值14.5取整为14
1   小明   15         英语            92
2   小红   14         数学            95
3   小红   14         英语             0   # 成绩缺失用0填充
4   小刚   15         数学            78
5   小刚   15         英语            82

2. 数据统计与聚合(分组统计)

示例 1:计算各科平均分、最高分

python

运行

python 复制代码
import pandas as pd

df = pd.read_csv("students_data.csv", encoding="utf-8", dtype={"course_score": int})

# 按课程分组,统计成绩的均值、最高分、最低分
course_stats = df.groupby("course_name")["course_score"].agg(["mean", "max", "min"])
# 重命名列名,更易读
course_stats.columns = ["平均分", "最高分", "最低分"]
# 保留1位小数
course_stats = course_stats.round(1)

print("各科成绩统计:")
print(course_stats)
运行结果

plaintext

plaintext 复制代码
各科成绩统计:
            平均分  最高分  最低分
course_name              
数学          86.0    95    78
英语          87.3    92    80
示例 2:按姓名分组,计算每个学生的总分和平均分

python

运行

python 复制代码
# 按姓名分组,计算总分和课程数量
student_stats = df.groupby("name").agg(
    总分=("course_score", "sum"),
    课程数量=("course_name", "count"),
    平均分=("course_score", "mean")
).round(1)

print("\n各学生成绩统计:")
print(student_stats)
运行结果

plaintext

plaintext 复制代码
各学生成绩统计:
      总分  课程数量  平均分
name               
小明   177      2    88.5
小红   183      2    91.5
小刚   160      2    80.0

聚合技巧 :用groupby("分组列")指定分组依据,用agg()指定要计算的统计指标(sum、count、mean 等),灵活且高效。

六、综合实操:学生成绩分析系统(Pandas 版)

咱们结合前面的学生数据,用 Pandas 实现一个 "学生成绩分析系统",完成以下功能:

  1. 读取 CSV 文件中的学生课程数据;
  2. 清洗数据(处理缺失值、修正错误成绩);
  3. 筛选 "平均分> 85 的优秀学生";
  4. 统计各科成绩分布(A/B/C 等级的数量);
  5. 将分析结果保存为 Excel 文件(方便后续查看)。

完整代码

python

运行

python 复制代码
import pandas as pd

def student_score_analysis(input_file="students_data.csv", output_file="analysis_result.xlsx"):
    print("===== 学生成绩分析系统 =====")
    
    # 1. 读取数据
    print("\n1. 读取数据...")
    df = pd.read_csv(
        input_file,
        encoding="utf-8",
        dtype={"course_score": int}
    )
    print(f"成功读取 {len(df)} 条数据")

    # 2. 数据清洗(假设存在缺失值,此处模拟处理)
    print("\n2. 数据清洗...")
    # 填充缺失的年龄(用均值)和成绩(用0)
    if df["age"].isnull().any():
        df["age"].fillna(df["age"].mean().astype(int), inplace=True)
    if df["course_score"].isnull().any():
        df["course_score"].fillna(0, inplace=True)
    # 修正错误数据(比如成绩>100的改为100)
    df.loc[df["course_score"] > 100, "course_score"] = 100
    print("数据清洗完成")

    # 3. 添加辅助列(成绩等级、学生总分)
    print("\n3. 计算辅助数据...")
    # 成绩等级
    df["grade"] = df["course_score"].apply(
        lambda x: "A" if x >= 90 else ("B" if x >= 80 else "C")
    )
    # 按姓名计算总分,合并到原数据
    student_total = df.groupby("name")["course_score"].sum().reset_index()
    student_total.columns = ["name", "total_score"]
    df = pd.merge(df, student_total, on="name")  # 按姓名合并
    # 计算平均分
    df["avg_score"] = df["total_score"] / 2  # 假设每个学生2门课
    print("辅助数据计算完成")

    # 4. 数据筛选(优秀学生:平均分>85)
    print("\n4. 筛选优秀学生(平均分>85)...")
    excellent_students = df[["name", "total_score", "avg_score"]].drop_duplicates("name")
    excellent_students = excellent_students[excellent_students["avg_score"] > 85].sort_values("avg_score", ascending=False)
    print("优秀学生列表:")
    print(excellent_students)

    # 5. 数据统计(各科等级分布)
    print("\n5. 各科等级分布统计...")
    grade_distribution = pd.crosstab(df["course_name"], df["grade"], margins=True)
    grade_distribution.columns = ["C级(<80)", "B级(80-89)", "A级(90+)", "总计"]
    grade_distribution.index.name = "课程"
    print("各科等级分布:")
    print(grade_distribution)

    # 6. 保存结果到Excel(多个工作表)
    print(f"\n6. 保存结果到 {output_file}...")
    with pd.ExcelWriter(output_file, engine="openpyxl") as writer:
        df.to_excel(writer, sheet_name="完整数据", index=False)
        excellent_students.to_excel(writer, sheet_name="优秀学生", index=False)
        grade_distribution.to_excel(writer, sheet_name="等级分布")
    print("结果保存完成!")

    print("\n===== 分析结束 =====")
    return df, excellent_students, grade_distribution

# 运行分析系统
if __name__ == "__main__":
    student_score_analysis()

关键功能说明

  1. 数据合并 :用pd.merge()将学生总分合并到原数据,避免手动循环匹配;
  2. 去重 :用drop_duplicates()去除学生重复行(每个学生只保留一条总分记录);
  3. 交叉表统计 :用pd.crosstab()快速生成 "课程 - 等级" 的分布表,比手动统计简洁;
  4. 多工作表保存 :用pd.ExcelWriter()将不同结果保存到 Excel 的多个工作表,方便查看。

运行结果(节选)

plaintext

plaintext 复制代码
===== 学生成绩分析系统 =====

1. 读取数据...
成功读取 6 条数据

2. 数据清洗...
数据清洗完成

3. 计算辅助数据...
辅助数据计算完成

4. 筛选优秀学生(平均分>85)...
优秀学生列表:
  name  total_score  avg_score
1   小红         183       91.5
0   小明         177       88.5

5. 各科等级分布统计...
各科等级分布:
课程   C级(<80)  B级(80-89)  A级(90+)  总计
数学         1          1         1     3
英语         0          2         1     3
总计         1          3         2     6

6. 保存结果到 analysis_result.xlsx...
结果保存完成!

===== 分析结束 =====

七、新手必踩的 5 个坑:避坑指南

Pandas 功能强大,但新手容易在 "数据类型""索引""缺失值" 等方面踩坑,咱们总结 5 个高频问题:

坑 1:数据类型不匹配(比如成绩是字符串)

python

运行

python 复制代码
# 错误示例:course_score是字符串,无法比较大小
df = pd.read_csv("students_data.csv", encoding="utf-8")
# 此时df["course_score"]是object类型(字符串)
print(df[df["course_score"] > 85])  # 报错:TypeError: '>' not supported between instances of 'str' and 'int'

解决 :读取时用dtype指定列类型:

python

运行

python 复制代码
df = pd.read_csv("students_data.csv", encoding="utf-8", dtype={"course_score": int})

坑 2:用=修改数据不生效(忘记inplace=True

python

运行

python 复制代码
# 错误示例:fillna()默认不修改原数据,需要inplace=True
df["age"].fillna(df["age"].mean())  # 原df的age列无变化
print(df["age"].isnull().sum())  # 仍为1(缺失值未填充)

解决 :添加inplace=True或重新赋值:

python

运行

python 复制代码
df["age"].fillna(df["age"].mean(), inplace=True)  # 正确
# 或 df["age"] = df["age"].fillna(df["age"].mean())

坑 3:筛选多条件时用and/or而非&/|

python

运行

python 复制代码
# 错误示例:多条件用and,报错
df[(df["age"] == 15) and (df["course_name"] == "英语")]
# 报错:ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

解决 :Pandas 多条件用&(且)、|(或),每个条件加括号:

python

运行

python 复制代码
df[(df["age"] == 15) & (df["course_name"] == "英语")]  # 正确

坑 4:读取 Excel 时缺少依赖(openpyxl/xlrd)

python

运行

python 复制代码
# 错误示例:未安装openpyxl,读取.xlsx文件报错
df = pd.read_excel("students_data.xlsx")
# 报错:Missing optional dependency 'openpyxl'. Install using 'pip install openpyxl'.

解决:安装对应依赖:

bash

运行

bash 复制代码
pip install openpyxl  # 读取.xlsx
pip install xlrd       # 读取.xls

坑 5:lociloc混淆(按索引 vs 按位置)

python

运行

python 复制代码
# 错误示例:用iloc按索引访问,报错
df_idx = df.set_index("name")  # 索引改为姓名
print(df_idx.iloc["小明"])  # 报错:ValueError: Location based indexing can only have [integer, integer slice (START point is INCLUDED, END point is EXCLUDED), listlike of integers, boolean array] types

解决loc按索引访问,iloc按位置访问:

python

运行

python 复制代码
print(df_idx.loc["小明"])  # 正确(按索引"小明")
print(df_idx.iloc[0])     # 正确(按位置0)

八、小结与下一篇预告

这篇你学到了什么?

  1. Pandas 基础 :安装 Pandas,理解Series(一维)和DataFrame(二维表格)的核心结构;
  2. 数据读取 :用read_csv()/read_excel()一行读取表格数据,对比csv模块更高效;
  3. 数据查看 :用head()/info()/describe()快速了解数据全貌,不用手动循环;
  4. 数据操作:筛选(条件筛选、列选择)、修改(值修改、添加新列)、清洗(缺失值、重复值);
  5. 数据统计 :用groupby()/agg()/crosstab()实现分组统计,轻松生成分析报告;
  6. 实战应用:完成学生成绩分析系统,从读取到保存的完整流程,落地实用。

下一篇预告

今天的 Pandas 让我们能高效处理表格数据,但 "光有数据统计还不够,可视化才能让数据更直观"------ 比如用图表展示各科成绩分布、优秀学生占比。下一篇咱们会学 Python 的数据可视化库MatplotlibSeaborn,结合 Pandas 数据生成柱状图、折线图、饼图,让你的数据分析结果 "一目了然"。

如果这篇内容帮你掌握了 Pandas,欢迎在评论区分享你的 "数据分析案例"(比如用 Pandas 分析你的考试成绩),咱们一起交流进步~

相关推荐
ccLianLian2 小时前
CASS总结
人工智能·深度学习
三更两点2 小时前
构建企业级智能体AI系统的七层架构
人工智能·架构
Together_CZ2 小时前
DarkIR: Robust Low-Light Image Restoration——鲁棒的低光照图像复原
python·image·robust·darkir·鲁棒的低光照图像复原·low-light·restoration
探索宇宙真理.2 小时前
WordPress AI Engine信息泄露漏洞 | CVE-2025-11749 复现&研究
人工智能·经验分享·开源·安全漏洞
_妲己2 小时前
stable diffusion的MLSD直线(AI室内设计)
人工智能·stable diffusion
拾贰_C2 小时前
【python | pytorch | scipy】scipy scikit-learn库相互依赖?
pytorch·python·scipy
FF-Studio2 小时前
Ubuntu 24.04 磁盘爆满“灵异“事件:Btrfs, Snapper 与删不掉的空间
linux·运维·人工智能·ubuntu
BoBoZz192 小时前
PolyDataContourToImageData 3D集合图像转换成等效3D二值图像
python·vtk·图形渲染·图形处理
2401_841495642 小时前
【自然语言处理】关系性形容词的特征
人工智能·python·自然语言处理·自动识别·特征验证·关系性形容词·语言学规则和计算