本课导读
"把上海的订单挑出来""看一下金额前三的行""只要产品和金额两列"——数据分析一半的日常就是从大表里取你要的那块。本课学三套选取姿势:方括号选列、loc/iloc 选行、布尔筛选按条件挑行(本课的重头戏,也是 pandas 最有表现力的语法)。学完这课,你对一张表就真正做到指哪打哪。预计 60 分钟。
道具表(本课通用)
Python
import pandas as pd
raw = """order_id,product,price,qty,city
1001,键盘,299,1,上海
1002,鼠标,89,2,北京
1003,显示器,1599,1,上海
1004,键盘,299,3,深圳
1005,鼠标,89,1,北京
1006,耳机,459,2,上海"""
with open("orders.csv", "w", encoding="utf-8") as f:
f.write(raw)
df = pd.read_csv("orders.csv")
df["total"] = df["price"] * df["qty"]
print(df)
(后面每个代码块都会重建这份道具——沙盒约定,任意顺序运行不炸。)
一、选列:方括号两副面孔
Python
import pandas as pd
raw = """order_id,product,price,qty,city
1001,键盘,299,1,上海
1002,鼠标,89,2,北京
1003,显示器,1599,1,上海
1004,键盘,299,3,深圳"""
with open("orders.csv", "w", encoding="utf-8") as f:
f.write(raw)
df = pd.read_csv("orders.csv")
one = df["product"] # 单列:字符串 → Series
some = df[["product", "price"]] # 多列:列表 → DataFrame(注意双层方括号)
print(type(one).__name__, type(some).__name__)
print(some)
规则一句话:方括号里放列名字符串得 Series,放列名列表得 DataFrame。双层方括号看着怪,拆开看就懂——外层是取数动作,内层 ["product", "price"] 是一个普通列表。
二、选行:loc 按标签,iloc 按位置
Python
import pandas as pd
raw = """order_id,product,price,qty,city
1001,键盘,299,1,上海
1002,鼠标,89,2,北京
1003,显示器,1599,1,上海
1004,键盘,299,3,深圳"""
with open("orders.csv", "w", encoding="utf-8") as f:
f.write(raw)
df = pd.read_csv("orders.csv")
print(df.iloc[0]) # iloc:按位置(第 0 行)——integer location
print("―" * 30)
print(df.iloc[-1]["product"]) # 最后一行的 product
print(df.iloc[0:2]) # 位置切片:前两行(U1.1 切片,含头不含尾)
print("―" * 30)
print(df.loc[2, "product"]) # loc:按标签(行标签 2,列 product)
print(df.loc[0:2, ["product", "price"]]) # 注意!loc 切片含两端
一对双胞胎,分工记牢:
- iloc = 按位置(integer):第几行第几列,规则和列表切片完全一致(含头不含尾)
- loc = 按标签:行标签 + 列名。有个偏门脾气——loc 的切片含两端(
0:2 是三行),因为标签切片"到 2 为止"比"到 2 之前"更符合直觉
- 现阶段行标签就是自动编号,两者看着像;将来遇到"日期做行标签"的表,loc 的价值才完全展开。先建立肌肉:位置用 iloc,标签/列名用 loc
三、布尔筛选:本课的主菜
上一课埋的伏笔收网。"整列比较"得到一列 True/False,把它塞回方括号——True 的行留下:
Python
import pandas as pd
raw = """order_id,product,price,qty,city
1001,键盘,299,1,上海
1002,鼠标,89,2,北京
1003,显示器,1599,1,上海
1004,键盘,299,3,深圳
1005,鼠标,89,1,北京
1006,耳机,459,2,上海"""
with open("orders.csv", "w", encoding="utf-8") as f:
f.write(raw)
df = pd.read_csv("orders.csv")
df["total"] = df["price"] * df["qty"]
# 第一步:条件本身是一列 True/False(先单独看看它)
mask = df["city"] == "上海"
print(mask)
print("―" * 30)
# 第二步:塞回方括号 → True 的行留下
print(df[mask])
print("―" * 30)
# 熟练后一步到位(最常见的写法):
print(df[df["total"] > 500])
读法口诀:df[df["total"] > 500] 读作"df 里 total 大于 500 的那些行"——里层造筛子,外层过筛子。
组合条件,两个新符号两个坑:
Python
import pandas as pd
raw = """order_id,product,price,qty,city
1001,键盘,299,1,上海
1002,鼠标,89,2,北京
1003,显示器,1599,1,上海
1004,键盘,299,3,深圳
1005,鼠标,89,1,北京
1006,耳机,459,2,上海"""
with open("orders.csv", "w", encoding="utf-8") as f:
f.write(raw)
df = pd.read_csv("orders.csv")
df["total"] = df["price"] * df["qty"]
# 且:& (不是 and!);每个条件必须加括号!
print(df[(df["city"] == "上海") & (df["total"] > 500)])
print("―" * 30)
# 或:| (不是 or!)
print(df[(df["product"] == "键盘") | (df["product"] == "耳机")])
print("―" * 30)
# “在名单里”:isin,比连串 or 优雅(U1.1 集合思维的表格版)
print(df[df["product"].isin(["键盘", "耳机"])])
说明
布尔筛选两大坑,新手命中率 90%:① 用了 and/or——整列比较必须用 & 和 |(and/or 是单个值的逻辑词,对整列直接报错);② 忘加括号——& 的优先级高于比较运算,df["a"] > 1 & df["b"] < 2 会先算中间的 &,报一堆看不懂的错。肌肉记忆:每个条件独立包括号。
四、排序 + 取头部:TopN 连招
Python
import pandas as pd
raw = """order_id,product,price,qty,city
1001,键盘,299,1,上海
1002,鼠标,89,2,北京
1003,显示器,1599,1,上海
1004,键盘,299,3,深圳
1005,鼠标,89,1,北京
1006,耳机,459,2,上海"""
with open("orders.csv", "w", encoding="utf-8") as f:
f.write(raw)
df = pd.read_csv("orders.csv")
df["total"] = df["price"] * df["qty"]
# 金额前三的订单:排序 + head(U1.1 的 sorted()[:3] 表格版)
top3 = df.sort_values("total", ascending=False).head(3)
print(top3)
print("―" * 30)
# 连招续一手:只看这三单的产品和金额
print(top3[["product", "total"]])
sort_values("列", ascending=False) 降序排(注意:交回新表,原表不动——sorted() 的脾气,不是 .sort() 的)。链式连招 df.sort_values(...).head(3)[["列"]] 一行完成"排序 → 取前三 → 挑列",这种流水线式写法是 pandas 的日常体态。
✍️ 练习
练习 1:三种选取各来一下
从道具表中:① 取 product 单列 ② 取 product 和 city 两列 ③ 用 iloc 取最后两行。
Python
import pandas as pd
raw = """order_id,product,price,qty,city
1001,键盘,299,1,上海
1002,鼠标,89,2,北京
1003,显示器,1599,1,上海
1004,键盘,299,3,深圳"""
with open("orders.csv", "w", encoding="utf-8") as f:
f.write(raw)
df = pd.read_csv("orders.csv")
# 你的代码写在下面
✅ 参考答案
import pandas as pd
raw = """order_id,product,price,qty,city
1001,键盘,299,1,上海
1002,鼠标,89,2,北京
1003,显示器,1599,1,上海
1004,键盘,299,3,深圳"""
with open("orders.csv", "w", encoding="utf-8") as f:
f.write(raw)
df = pd.read_csv("orders.csv")
print(df["product"])
print(df[["product", "city"]])
print(df.iloc[-2:])
练习 2:筛选实战
行政小美查报销:筛出 ① 金额超 200 的餐费 ② 部门是"设计"或"运营"的全部报销(用 isin)。
Python
import pandas as pd
raw = """name,dept,type,amount
小雨,设计,餐费,180
阿杰,运营,交通,95
丽丽,设计,餐费,260
老王,销售,餐费,320
小陈,运营,办公,150"""
with open("expense.csv", "w", encoding="utf-8") as f:
f.write(raw)
df = pd.read_csv("expense.csv")
# 你的代码写在下面
💡 提示
① 两个条件(type 是餐费 且 amount > 200)——& 加括号。② df["dept"].isin([...])。
✅ 参考答案
import pandas as pd
raw = """name,dept,type,amount
小雨,设计,餐费,180
阿杰,运营,交通,95
丽丽,设计,餐费,260
老王,销售,餐费,320
小陈,运营,办公,150"""
with open("expense.csv", "w", encoding="utf-8") as f:
f.write(raw)
df = pd.read_csv("expense.csv")
print(df[(df["type"] == "餐费") & (df["amount"] > 200)])
print(df[df["dept"].isin(["设计", "运营"])])
练习 3:连招挑战
一行链式完成:筛出北京和上海的订单 → 按 total 降序 → 取前两名 → 只显示 city、product、total 三列。
Python
import pandas as pd
raw = """order_id,product,price,qty,city
1001,键盘,299,1,上海
1002,鼠标,89,2,北京
1003,显示器,1599,1,上海
1004,键盘,299,3,深圳
1005,鼠标,89,1,北京
1006,耳机,459,2,上海"""
with open("orders.csv", "w", encoding="utf-8") as f:
f.write(raw)
df = pd.read_csv("orders.csv")
df["total"] = df["price"] * df["qty"]
# 你的代码写在下面(一行链式,可适当换行)
✅ 参考答案
import pandas as pd
raw = """order_id,product,price,qty,city
1001,键盘,299,1,上海
1002,鼠标,89,2,北京
1003,显示器,1599,1,上海
1004,键盘,299,3,深圳
1005,鼠标,89,1,北京
1006,耳机,459,2,上海"""
with open("orders.csv", "w", encoding="utf-8") as f:
f.write(raw)
df = pd.read_csv("orders.csv")
df["total"] = df["price"] * df["qty"]
result = (
df[df["city"].isin(["北京", "上海"])]
.sort_values("total", ascending=False)
.head(2)[["city", "product", "total"]]
)
print(result)
外面包一层圆括号就能把长链断行——可读性和链式两不误(PEP8 行长规矩的 pandas 应用)。
📝 随堂测验
1. df[["a", "b"]] 双层方括号的含义是?
2. iloc 和 loc 的分工是?
3. df[df["total"] > 500] 的工作原理是?
4. df[(df["a"] > 1) & (df["b"] < 5)] 里,为什么不能写 and、为什么要括号?
5. “挑出产品在指定清单里的行”,最优雅的写法是?
本课小结
- 选列:字符串→Series,列表→DataFrame(双层方括号);选行:位置 iloc(含头不含尾)、标签 loc(含两端)
- 布尔筛选 = 造筛子(整列比较)+ 过筛子(塞回方括号);组合用
& | 且每个条件包括号,名单用 isin
- TopN 连招:
sort_values(..., ascending=False).head(n)——sort_values 交新表不动原表
- 链式流水线是 pandas 的日常体态,长链包圆括号断行
下一课直面真实数据的常态——脏:缺失、重复、类型错乱、空格幽灵,一门课学会给数据"洗澡"。