掌握 .loc、.iloc 和布尔索引是高效使用 pandas 的核心技能。
.loc[]— 按标签索引(label-based)
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)
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]) # 每隔一行
.locvs.iloc对比
| .loc[] | .iloc[] | |
|---|---|---|
| 索引依据 | 标签(label) | 位置(integer position) |
| 切片包含 | 含两端 | 不含右端(python 语义) |
| 行索引是数字时 | 按索引值 | 按位置 |
| 列选择 | 列名 | 列位置 |
| 布尔索引 | ✅ 支持 | ❌ 不支持 |
重要: 当索引是 0,1,2…时,.loc[1] 和 .iloc[1] 看起来一样但含义完全不同!
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 更快,但只能取单个值。
# at: 按标签取单个值 print(df.at['b', '工资']) # 12000 # iat: 按位置取单个值 print(df.iat[0, 3]) # 8000 # 也可用于赋值 df.at['b', '工资'] = 13000 df.iat[0, 3] = 8500
布尔索引 — 条件筛选
基本条件
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, ['姓名', '城市']])
常见筛选方法
# 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()— 字符串表达式筛选
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()— 条件保留/替换
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
列的选择与操作
# 单列: 返回 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, '性别', ['男', '女', '男', '男', '男'])
行操作
# 添加行
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) |
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论