本文讲解 Pandas 最核心的数据选取语法:
[]、loc、iloc、at、iat,区分标签选取和位置选取,附带布尔索引、条件筛选、多条件、isin、query 等实战用法,以及常见踩坑点,承接前面系列教程风格。
前置导入与示例数据
import pandas as pd
import numpy as np
# 构造示例数据
df = pd.DataFrame({
"name": ["张三", "李四", "王五", "赵六", "孙七"],
"age": [22, 25, 30, 28, 35],
"city": ["杭州", "上海", "杭州", "北京", "上海"],
"salary": [8000, 12000, 15000, 11000, 18000]
}, index=[101, 102, 103, 104, 105])
print(df)
一、核心概念区分
- 标签(label):行索引名称、列名,对应
loc、at - 位置(position):从0开始的数字下标,对应
iloc、iat
重点:当索引是自定义数字(不是0,1,2…)时,
[]和iloc极易混淆,是新手高频错误点。
二、基础方括号 [] 选取
[] 优先识别列,其次支持布尔行筛选,不推荐用来取单行。
2.1 选取单列
# 返回 Series
s = df["name"]
# 返回 DataFrame(双层括号)
df_name = df[["name"]]
2.2 选取多列
df_sub = df[["name", "age", "salary"]]
2.3 切片(仅行切片,注意:是标签切片,不是位置!)
⚠️ 只有索引有序时,df[start:end] 是标签切片,包含 end
# 索引标签 101 ~ 103
df[101:103]
不建议用
df[0:2]这种写法,可读性差,优先 iloc。
三、loc:按标签选取(最常用)
语法:df.loc[行条件, 列标签]
loc 切片是闭区间,包含结束标签
3.1 单行选取
# 取 index=102 的一行
df.loc[102]
# 取单行,返回DataFrame
df.loc[[102]]
3.2 多行选取
# 指定多个标签
df.loc[[101,103,105]]
# 标签切片
df.loc[101:104]
3.3 同时指定行+列
# 行102,列 name、salary
df.loc[102, ["name", "salary"]]
3.4 布尔条件筛选(loc 首选)
# 年龄大于28
df.loc[df["age"] > 28]
# 多条件:& 并且,| 或者,~ 取反,每个条件必须加括号
df.loc[(df["age"] > 25) & (df["city"] == "杭州")]
四、iloc:按位置下标选取
语法:df.iloc[行位置, 列位置]
下标从0开始;切片是左闭右开,不包含结束位置,和Python列表一致
4.1 单行、多行
# 第0行
df.iloc[0]
# 0、2行
df.iloc[[0,2]]
# 0~2行(不含第3行)
df.iloc[0:3]
4.2 行+列位置
# 第1行,第0、3列
df.iloc[1, [0,3]]
# 前3行,前2列
df.iloc[0:3, 0:2]
一句话区分 loc / iloc
loc:看名字(标签);iloc:看排第几(位置)
五、at / iat:快速取单个值(性能更高)
at:按标签取单个单元格iat:按位置取单个单元格
适合循环里只拿一个值,比 loc/iloc 更快
# index=103,列 age
df.at[103, "age"]
# 第2行,第1列
df.iat[2, 1]
⚠️ 只能取单个值,不能切片、不能批量选。
六、常用条件筛选技巧
6.1 isin 包含匹配
# 城市在列表内
df.loc[df["city"].isin(["杭州","上海"])]
# 取反,不在里面
df.loc[~df["city"].isin(["北京"])]
6.2 str 字符串匹配(需要列是string/object类型)
df.loc[df["name"].str.contains("五")]
6.3 query() 表达式筛选(写法简洁,适合复杂条件)
df.query("age > 28 and city == '上海'")
# 变量传入,用 @
min_salary = 12000
df.query("salary >= @min_salary")
七、布尔索引的小细节
布尔数组长度必须和 DataFrame 行数一致
cond = df["salary"] > 10000
print(cond)
df[cond]
# 等价
df.loc[cond]
推荐统一写
df.loc[cond, 列],可以直接指定输出列,避免再切片
八、选取后赋值(重要)
Pandas 链式选取容易触发 SettingWithCopyWarning
✅ 推荐 loc 原地赋值
# 杭州员工薪资 +1000
df.loc[df["city"]=="杭州", "salary"] = df.loc[df["city"]=="杭州", "salary"] + 1000
❌ 不推荐链式:df[df.city=="杭州"]["salary"] += 1000,会产生警告,赋值可能失效
九、选取方式选型对照表
| 方法 | 依据 | 支持切片 | 支持条件 | 适用场景 |
|---|---|---|---|---|
| [] | 列名 / 布尔行 | 有限 | ✅ | 简单取列、布尔筛选 |
| loc | 索引标签、列名 | ✅(闭区间) | ✅ | 绝大多数业务筛选,优先推荐 |
| iloc | 数字位置 | ✅(左闭右开) | ❌ | 固定顺序、按行号提取 |
| at | 标签 | ❌ | ❌ | 单个单元格取值 |
| iat | 位置 | ❌ | ❌ | 单个单元格快速取值 |
| query | 表达式 | ❌ | ✅ | 条件多、想写清爽代码 |
十、高频坑点汇总
- 索引不是0开始,混淆 loc 和 iloc
比如 index=101,df[101]是loc逻辑,不是第1行;取第1行要用iloc[0] - 多条件忘记加括号:
df["age"]>25 & df["city"]=="杭州"直接报错 - loc切片包含末尾,iloc不包含,和原生Python切片习惯不一样
- 链式选取 SettingWithCopyWarning:修改数据尽量用 loc 一次性赋值
- 布尔索引长度不匹配:筛选Series和原df行数不一致时报错
- at只支持单个值,不能传列表、切片
十一、综合实战模板
# 筛选:上海、薪资大于10000,只保留 name age salary
res = df.loc[
(df["city"] == "上海") & (df["salary"] > 10000),
["name", "age", "salary"]
]
print(res)
0 条笔记