Ch01: Python数据处理学习笔记
本文对应教程:第1章: Python数据处理
1. DataFrame 是什么?
- 可以把
DataFrame理解成“带列名的表格”。 - 行通常是一条样本记录(一个乘客),列是特征字段(年龄、舱位等)。
- 两个最常用的对象:
df:整张表(DataFrame)s:一列(Series,类似单列)
关键区别:
df["age"]取出来是一列(Series)df[["age", "fare"]]取出来是两列(DataFrame)
2. 读取数据与路径(本地优先)
这章建议用本地 CSV(已经在工作区准备好):
- 数据文件:ml-work/data/titanic.csv
常见坑:
- 相对路径是“相对于当前运行目录(working directory)”,不是相对于你以为的文件夹。
- 如果找不到文件(FileNotFoundError),先确认当前工作目录:
os.getcwd()。
3. “体检三件套”:结构、类型、样例
刚读入数据后,建议按顺序做:
3.1 看数据有多大
df.shape:返回 (行数, 列数)len(df):行数
3.2 看有哪些列
df.columns:所有列名list(df.columns):把列名变成列表,方便复制/挑选
3.3 看每列是什么类型
df.dtypes:每列 dtype(数值、字符串、布尔、类别等)
要关注的信号:
- 本该是数值的列却显示为
object(通常是字符串混入/缺失值格式不统一) - 类别列(例如 sex、embarked)通常是
object,后续建模需要编码(第 5 章会系统做)
3.4 看几行样例
df.head():看前 5 行df.tail():看最后 5 行df.sample(n=5, random_state=0):随机抽 5 行(更能发现脏数据)
4. 缺失值:怎么发现、怎么表达、怎么处理
4.1 怎么发现缺失
df.isna():True/False 表df.isna().sum():每列缺失数量df.isna().mean():每列缺失比例(0~1)
常见做法:
- 先把缺失率按从高到低排序:
sort_values(ascending=False) - 只看前 10 个缺失最多的列:
head(10)
4.2 缺失值策略(不要“默认填 0”)
你需要能说清楚“为什么这样做”,常见策略:
- 删除(drop):
- 适合:缺失极多且列不重要,或缺失行很少
- 风险:可能引入偏差(缺失并非随机)
- 填充(fill):
- 数值列:常用中位数(median)或均值(mean)
- 类别列:常用众数(mode)或填一个特殊值如 "UNK"
- 风险:会改变分布;要在 README 里记录
建议在 Titanic 上先做“最简单且可解释”的:
age:中位数填充(对极端值更稳)embarked:填 "UNK"(明确表示未知类别)
5. 频数统计:value_counts(非常常用)
当一列是“类别/标签”时,第一眼看:
s.value_counts():每个类别的计数s.value_counts(normalize=True):每个类别的比例
典型用途:
- 看标签是否不均衡(比如 survived 的 0/1 比例)
- 看某个类别列是否有脏值(拼写不一致、大小写混乱等)
6. 选列、删列、改列名(让数据变“你能控制”)
6.1 只保留一组列
- 先写一个
keep = [...]列表,然后用df = df[keep]
6.2 删除列
df.drop(columns=[...])
6.3 改列名
df.rename(columns={"old": "new"})
为什么要做这些:
- EDA 时列太多会分散注意力;本章先聚焦“最常用的 7~10 列”即可。
7. 过滤与排序:把“问题”变成“子集”
常见操作:
- 过滤行:
df[条件]- 例:
df[df["age"].notna()]表示只取年龄不缺失的行
- 例:
- 排序:
df.sort_values("fare", ascending=False)
你在写问题时可以用这种句式:
- “只看某个舱位的人”
- “只看有年龄记录的人”
- “按票价从高到低看极端样本”
8. 分组统计:groupby(从“表”得到“结论数字”)
核心思路:
- 先按某列分组(比如 pclass)
- 再对另一列做聚合(比如 survived 的均值 = 幸存率)
常见聚合:
mean:均值(二分类的均值就是比例)median:中位数(更稳)count/size:数量
Titanic 最常用:
df.groupby("pclass")["survived"].mean():不同舱位幸存率df.groupby("sex")["survived"].mean():男女幸存率
9. describe:快速得到数值列分布概览
df.describe():数值列的 count/mean/std/min/四分位数/max
你要关注:
- count 明显小于总行数:说明缺失多
- min/max 极端离谱:可能有异常值或录入错误
10. 画图的最小心法(本章只要“能回答问题”)
不需要追求复杂可视化,先掌握 3 种图:
- 直方图(分布):一个数值列长什么样
- 适合:age、fare
- 柱状图(对比):不同类别的均值/比例
- 适合:pclass 对 survival rate
- 箱线图(对比分布):两组之间的差异
- 适合:fare 在 survived=0/1 的差异
画图时写结论的模板(强烈建议你直接照抄):
- “图回答的问题是:____”
- “我观察到:____”
- “可能的解释是:____(可选)”
- “下一步我想验证:____(可选)”
11. 导出干净数据(让结果可复现)
df.to_csv("clean.csv", index=False):导出 CSV
练习
- 画一张不同舱位对应存活率的柱状图
python
import matplotlib.pyplot as plt
# 1) 分组 + 求均值(survived 是 0/1,均值就是存活率)
survival_by_class = df.groupby("pclass")["survived"].mean().sort_index()
# 上面这种链式调用看起来会比较混乱,对于新手来说不是很友好,所以选择下面这四行的方式会更轻松一些
g = df.groupby("pclass") # ① 按 pclass 分组:把数据按 1/2/3 舱位分成三堆
s = g["survived"] # ② 只取每一堆里的 survived 这一列(0/1)
rate = s.mean() # ③ 对每一堆求均值:0/1 的均值 = 1 的比例 = 存活率
survival_by_class = rate.sort_index() # ④ 按索引排序(让 1,2,3 按顺序显示)
# 2) 画柱状图
ax = survival_by_class.plot(kind="bar", title="Survival rate by pclass")
ax.set_xlabel("pclass")
ax.set_ylabel("survival rate")
# 3) 显示
plt.show()
数据清洗
数据清洗这件事,你可以按一个固定流程来做(每一步都能解释“我为什么这么做”)。我用 Titanic 做例子,但你以后换数据集也一样。
0) 先定目标:这次“干净”指什么
- 你后面要做监督学习(预测
survived),所以清洗目标通常是:- 选出一组你要用的列(特征 + 标签)
- 处理缺失值(让表里没有模型不能接受的 NaN,或明确保留 NaN)
- 处理类型(数值列真的是数值;类别列统一格式)
- 输出一个可复现的
clean.csv
1) 选列(先少后多) 建议先只保留最常用的 8 列,降低复杂度:
- 标签:
survived - 特征:
pclass, sex, age, sibsp, parch, fare, embarked
为什么这么做:这些列信息量大、缺失相对可控、后续建模也方便。
2) 检查缺失:缺失率 + 缺失在哪里 你已经会算缺失率 top10 了。接下来你要做两件事:
- 记录哪些列缺失多(Titanic 通常是
age、embarked少量缺失,deck很多缺失) - 决定策略:删/填/保留
3) 缺失值策略(Titanic 的“新手可解释方案”)
age(数值):用中位数填充
理由:中位数对极端值更稳;先跑通流程最重要。embarked(类别):用"UNK"填充
理由:明确表示未知类别,不会把缺失“伪装成真实港口”。- 其他列如果缺失很少:你也可以选择“直接删掉缺失行”,但要写清楚删了多少行、为什么删。
4) 类型清洗(保证每列是你以为的类型) 重点看:
survived:确保是整数 0/1pclass, sibsp, parch:应该是整数age, fare:应该是数值(float)sex, embarked:字符串/类别都可以,但要保证没有奇怪空格、大小写混乱
一个简单的习惯:对字符串列做 strip() 去掉首尾空格(如果有)。
5) 异常值 / 逻辑检查(轻量但很重要) 不用复杂,先做“常识检查”:
age是否有 <0 或特别离谱的值fare是否有 <0pclass是否只包含 1/2/3 这些检查能帮你发现数据读错或脏值。
6) 产出与记录
- 导出:保存为
clean.csv - 记录(写在 README 或 notebook 文字里):
- 你保留了哪些列
- 每个缺失值处理的理由
- 清洗前后数据行数变化、缺失率变化(至少写一句)