自学教程 学编程从这里开始

Pandas 数据选取

本文讲解 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表达式❌✅条件多、想写清爽代码

十、高频坑点汇总

  1. 索引不是0开始,混淆 loc 和 iloc

    比如 index=101,df[101] 是loc逻辑,不是第1行;取第1行要用 iloc[0]
  2. 多条件忘记加括号:df["age"]>25 & df["city"]=="杭州" 直接报错
  3. loc切片包含末尾,iloc不包含,和原生Python切片习惯不一样
  4. 链式选取 SettingWithCopyWarning:修改数据尽量用 loc 一次性赋值
  5. 布尔索引长度不匹配:筛选Series和原df行数不一致时报错
  6. at只支持单个值,不能传列表、切片

十一、综合实战模板

# 筛选:上海、薪资大于10000,只保留 name age salary
res = df.loc[
    (df["city"] == "上海") & (df["salary"] > 10000),
    ["name", "age", "salary"]
]
print(res)
标签:

0 条笔记