Python-pandas-索引与筛选

Pandas 索引与筛选

掌握 .loc.iloc 和布尔索引是高效使用 Pandas 的核心技能。


🎯 .loc[] --- 按标签索引(Label-based)⭐

python 复制代码
import pandas as pd
import numpy as np

df = pd.DataFrame({
    '姓名': ['张三', '李四', '王五', '赵六', '钱七'],
    '年龄': [22, 25, 30, 28, 35],
    '城市': ['北京', '上海', '广州', '深圳', '杭州'],
    '工资': [8000, 12000, 15000, 10000, 18000]
}, index=['a', 'b', 'c', 'd', 'e'])

# 单行(按标签)
print(df.loc['b'])           # 返回 Series
# 姓名      李四
# 年龄       25
# 城市      上海
# 工资    12000

# 多行(标签列表)
print(df.loc[['a', 'c', 'e']])

# 标签切片(含两端!)
print(df.loc['b':'d'])        # 包含 b, c, d

# 行 + 列
print(df.loc['b', '工资'])            # 单个值: 12000
print(df.loc['b', ['姓名', '工资']])  # 行 + 列子集
print(df.loc[['a', 'c'], ['姓名', '年龄']])  # 多行多列

# 行 + 列切片
print(df.loc['b':'d', '姓名':'城市'])  # 行切片 + 列切片

# 带条件的列选择(使用布尔列表)
print(df.loc[df['工资'] > 10000, ['姓名', '工资']])

.loc 关键规则

规则 示例
包含结束值 df.loc['a':'c'] 包含 c
标签不存在会报错 KeyError
返回单个值是标量 df.loc['a', '年龄'] 返回 int
返回 Series 单行 df.loc['a'] 或单列 df.loc[:, '年龄']

🔢 .iloc[] --- 按位置索引(Integer-based)⭐

python 复制代码
df = pd.DataFrame({
    'A': [10, 20, 30, 40, 50],
    'B': [100, 200, 300, 400, 500],
    'C': ['a', 'b', 'c', 'd', 'e']
})

# 单行(按位置)
print(df.iloc[0])      # 第 0 行
print(df.iloc[-1])     # 最后一行

# 多行
print(df.iloc[[0, 2, 4]])     # 第 0, 2, 4 行
print(df.iloc[1:4])            # 第 1, 2, 3 行(不含 4!标准 Python 切片)

# 行 + 列
print(df.iloc[0, 1])           # 第 0 行第 1 列: 100
print(df.iloc[0:3, 0:2])       # 前 3 行, 前 2 列
print(df.iloc[:, :2])           # 所有行, 前 2 列
print(df.iloc[1:3, :])          # 第 1-2 行, 所有列

# 负数索引
print(df.iloc[-3:, :])          # 最后 3 行

# 等间隔取行
print(df.iloc[::2])             # 每隔一行

.loc vs .iloc 对比

.loc[] .iloc[]
索引依据 标签(label) 位置(integer position)
切片包含 两端 不含右端(Python 语义)
行索引是数字时 索引值 位置
列选择 列名 列位置
布尔索引 ✅ 支持 ❌ 不支持

重要 : 当索引是 0,1,2...时,.loc[1].iloc[1] 看起来一样但含义完全不同!

python 复制代码
df = pd.DataFrame({'val': [10, 20, 30]}, index=[2, 1, 0])
print(df.loc[1])    # 索引 = 1 的行 → val = 20
print(df.iloc[1])   # 第 1 行 → val = 20(巧合相同)
# 若 index=[5,3,1]: df.loc[1] 返回第三行,df.iloc[1] 返回第二行

🎯 at[] / iat[] --- 快速标量访问

.loc/.iloc 更快,但只能取单个值

python 复制代码
# at: 按标签取单个值
print(df.at['b', '工资'])     # 12000

# iat: 按位置取单个值
print(df.iat[0, 3])           # 8000

# 也可用于赋值
df.at['b', '工资'] = 13000
df.iat[0, 3] = 8500

🔍 布尔索引 --- 条件筛选 ⭐

基本条件

python 复制代码
df = pd.DataFrame({
    '姓名': ['张三', '李四', '王五', '赵六', '钱七'],
    '年龄': [22, 25, 30, 28, 35],
    '城市': ['北京', '上海', '广州', '深圳', '杭州'],
    '工资': [8000, 12000, 15000, 10000, 18000]
})

# 单个条件
print(df[df['年龄'] > 25])

# 多个条件(用 & 和 |,必须加括号!)
print(df[(df['年龄'] > 25) & (df['工资'] > 12000)])   # 且
print(df[(df['城市'] == '北京') | (df['城市'] == '上海')])  # 或
print(df[~(df['年龄'] < 30)])  # 非: 年龄 >= 30

# ♀️ 常见错误: 用 and/or 代替 &/|
# df[(df['年龄'] > 25) and (df['工资'] > 10000)]  ← 错误!
# df[(df['年龄'] > 25) & (df['工资'] > 10000)]    ← 正确

# 也可以用 .loc 配合布尔条件
print(df.loc[df['工资'] > 10000])
print(df.loc[df['工资'] > 10000, ['姓名', '城市']])

常见筛选方法

python 复制代码
# isin: 值在列表中
print(df[df['城市'].isin(['北京', '上海', '广州'])])

# 也可以用 ~ 取反
print(df[~df['城市'].isin(['深圳', '杭州'])])

# between: 值在范围内
print(df[df['年龄'].between(25, 30)])

# 字符串条件
print(df[df['姓名'].str.contains('张')])    # 名字含"张"
print(df[df['城市'].str.startswith('北')])  # 城市以"北"开头
print(df[df['城市'].str.len() == 2])       # 城市名长度为 2

# NaN 判断
print(df[df['列名'].isna()])    # 空值行
print(df[df['列名'].notna()])   # 非空值行

# any / all: 行列级布尔
print((df > 0).any())     # 每列是否有 >0 的值
print((df > 0).all())     # 每列是否所有值都 >0
print((df > 0).any(axis=1))  # 每行是否有 >0 的值

🔎 query() --- 字符串表达式筛选

python 复制代码
df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie', 'David'],
    'age': [25, 17, 35, 45],
    'salary': [5000, 3000, 8000, 12000],
    'city': ['NY', 'LA', 'NY', 'SF']
})

# 基本查询
print(df.query('age > 30'))
print(df.query('age > 25 and salary > 6000'))

# 外部变量引用(用 @)
threshold = 5000
print(df.query('salary > @threshold'))

# 字符串列
print(df.query('city == "NY"'))
print(df.query('city in ["NY", "SF"]'))

# 与 .loc 配合
print(df.query('age > 25')[['name', 'salary']])

📊 where() / mask() --- 条件保留/替换

python 复制代码
df = pd.DataFrame({
    'A': [1, 2, 3, 4, 5],
    'B': [10, 9, 8, 7, 6]
})

# where: 条件为 True 保留原值,False 替换为 NaN
print(df.where(df > 3))
#      A    B
# 0  NaN  10.0
# 1  NaN  9.0
# 2  NaN  8.0
# 3  4.0  7.0
# 4  5.0  6.0

# where + other: 不满足条件的用指定值代替
print(df.where(df > 3, other=0))

# mask: where 的反面(条件为 True 时替换)
print(df.mask(df > 3, other=0))
#    A  B
# 0  1  0
# 1  2  0
# 2  3  0
# 3  0  0
# 4  0  0

🎯 列的选择与操作

python 复制代码
# 单列: 返回 Series
print(df['姓名'])
print(df.姓名)  # 列名是合法标识符时可用点号

# 多列: 返回 DataFrame(注意双括号!)
print(df[['姓名', '工资']])

# 列赋值
df['奖金'] = df['工资'] * 0.1               # 新增列
df['总收入'] = df['工资'] + df['奖金']       # 基于现有列计算

# 删除列
df.drop('奖金', axis=1, inplace=True)        # axis=1 表示列
df.drop(['奖金', '总收入'], axis=1, inplace=True)

# 重命名列
df.rename(columns={'姓名': 'name', '年龄': 'age'}, inplace=True)

# 插入列(指定位置)
df.insert(1, '性别', ['男', '女', '男', '男', '男'])

🎯 行操作

python 复制代码
# 添加行
df.loc['f'] = ['孙九', 27, '成都', 14000]

# 通过 append 添加(创建新 DataFrame)
new_row = pd.DataFrame([['周十', 32, '重庆', 16000]],
                        columns=['姓名', '年龄', '城市', '工资'])
df = pd.concat([df, new_row], ignore_index=True)

# 删除行
df.drop('f', inplace=True)            # 按标签删
df.drop([0, 2], inplace=True)         # 按标签删

# 按条件删行
df = df[df['工资'] >= 10000]           # 保留工资 >= 10000
df = df[~df['城市'].isin(['深圳'])]    # 删除深圳的行

📝 索引筛选速查

需求 代码
按标签取行列 df.loc['a':'c', ['x', 'y']]
按位置取行列 df.iloc[0:5, 0:3]
单个标量(快) df.at['a', 'x'] / df.iat[0, 2]
条件筛选 df[df['col'] > 100]
多条件 df[(df['A'] > 3) & (df['B'] < 10)]
值在列表中 df[df['col'].isin([1, 2, 3])]
值在范围内 df[df['col'].between(3, 8)]
字符串过滤 df[df['col'].str.contains('abc')]
表达式查询 df.query('A > 3 and B < 10')
选列 df[['col1', 'col2']]
条件保留 df.where(df > 0, other=0)

\[pandas2-总览\|← 返回总览\]

相关推荐
一只小菜鸡..1 小时前
南京大学 操作系统 (JYY) 学习笔记:最终章——操作系统的宇宙,与我们的星辰大海
笔记·学习
青 春 记 忆1 小时前
LeetCode 53. 最大子数组和|Python 解法详解
python·算法·leetcode
鹿角片ljp1 小时前
Java面试复盘(二):String不可变、字符串常量池与字符串拼接
开发语言·python
讲温控就好了2 小时前
光刻温控的产业链价值:从精度指标到半导体制造竞争力
python·制造
小秋求学记.2 小时前
PHP安全漏洞实战:从环境配置到RCE攻击
开发语言·php
砚凝霜2 小时前
软考网络工程师|第 6 章 应用层安全协议、防火墙完整备考笔记
网络·笔记·安全
南极星10052 小时前
2026电赛E题有感
python·opencv·电赛
看浪的路人3 小时前
第3讲:代码补全引擎
开发语言·windows·python
小小龙学IT3 小时前
Day 26-27 项目实战:从零构建一个高并发聊天室(epoll + 线程池)
linux·服务器·c语言·开发语言·网络