pin_drop当前位置:知识文库 ❯ 图文
pandas DataFrame筛选过滤 - 条件表达式筛选数据
一、筛选过滤概述
数据筛选是数据分析中最常用的操作之一。pandas 提供了多种强大的筛选方式,可以根据单个或多个条件从 DataFrame 中提取满足条件的数据行。
掌握数据筛选可以帮助你快速找到目标数据、过滤异常值、筛选特定时间段或特定类别的记录。
二、基本筛选语法
比较运算符筛选
使用比较运算符生成布尔 Series,然后用它来筛选 DataFrame。
代码示例
# 等于
df[df['列名'] == 值]
# 不等于
df[df['列名'] != 值]
# 大于/小于
df[df['列名'] > 值]
df[df['列名'] < 值]
# 大于等于/小于等于
df[df['列名'] >= 值]
df[df['列名'] <= 值]使用 isin() 筛选
代码示例
# 筛选列值在指定列表中的行
df[df['列名'].isin(['值1', '值2', '值3'])]
# 取反:不在列表中的行
df[~df['列名'].isin(['值1', '值2'])]使用 between() 筛选
代码示例
# 筛选在指定范围内的行(默认包含两端)
df[df['列名'].between(最小值, 最大值)]
# 不包含两端
df[df['列名'].between(最小值, 最大值, inclusive='neither')]字符串筛选
代码示例
# 包含某字符串
df[df['列名'].str.contains('关键词')]
# 以某字符串开头
df[df['列名'].str.startswith('前缀')]
# 以某字符串结尾
df[df['列名'].str.endswith('后缀')]
# 正则表达式匹配
df[df['列名'].str.match(r'^[A-Z]')]三、多条件组合筛选
组合多个条件时,需要使用 位运算符,而不是 Python 的逻辑运算符。
重要提醒:每个条件必须用括号括起来!例如
df[(df['A'] > 0) & (df['B'] < 10)],不能写成df[df['A'] > 0 & df['B'] < 10]。
四、高级筛选方法
query() 方法
query() 提供了一种更简洁的筛选语法,特别适合复杂条件。
代码示例
# 使用query简化筛选
df.query('年龄 > 25 and 城市 == "北京"')
# 等同于
df[(df['年龄'] > 25) & (df['城市'] == '北京')]
# 使用变量
threshold = 20000
df.query('薪资 >= @threshold')缺失值筛选
代码示例
# 筛选缺失值的行
df[df['列名'].isnull()]
df[df['列名'].isna()]
# 筛选非缺失值的行
df[df['列名'].notnull()]
df[df['列名'].notna()]
# 筛选所有列都非缺失的行
df.dropna()
# 筛选至少有一个缺失值的行
df[df.isnull().any(axis=1)]重复值筛选
代码示例
# 筛选重复行
df[df.duplicated()]
# 筛选非重复行
df[~df.duplicated()]
# 按特定列筛选重复
df[df.duplicated(subset=['列1', '列2'])]五、代码示例
示例1:创建示例数据
代码示例
import pandas as pd
import numpy as np
# 创建员工数据
df = pd.DataFrame({
'姓名': ['张三', '李四', '王五', '赵六', '钱七', '孙八'],
'年龄': [25, 30, 28, 35, 22, 40],
'城市': ['北京', '上海', '广州', '深圳', '北京', '上海'],
'部门': ['技术', '市场', '技术', '人事', '技术', '财务'],
'薪资': [15000, 20000, 18000, 25000, 16000, np.nan],
'入职年份': [2020, 2019, 2021, 2018, 2022, 2015]
})
print(df)
# 姓名 年龄 城市 部门 薪资 入职年份
# 0 张三 25 北京 技术 15000.0 2020
# 1 李四 30 上海 市场 20000.0 2019
# 2 王五 28 广州 技术 18000.0 2021
# 3 赵六 35 深圳 人事 25000.0 2018
# 4 钱七 22 北京 技术 16000.0 2022
# 5 孙八 40 上海 财务 NaN 2015示例2:基本筛选
代码示例
# 筛选薪资大于18000的员工
print("=== 薪资 > 18000 ===")
print(df[df['薪资'] > 18000])
# 筛选技术部门的员工
print("\n=== 技术部门 ===")
print(df[df['部门'] == '技术'])
# 筛选城市在北京或上海的员工
print("\n=== 北京或上海 ===")
print(df[df['城市'].isin(['北京', '上海'])])
# 筛选年龄在25到35之间(包含)
print("\n=== 年龄25-35 ===")
print(df[df['年龄'].between(25, 35)]输出:
代码示例
=== 薪资 > 18000 ===
姓名 年龄 城市 部门 薪资 入职年份
1 李四 30 上海 市场 20000.0 2019
2 王五 28 广州 技术 18000.0 2021
3 赵六 35 深圳 人事 25000.0 2018
=== 技术部门 ===
姓名 年龄 城市 部门 薪资 入职年份
0 张三 25 北京 技术 15000.0 2020
2 王五 28 广州 技术 18000.0 2021
4 钱七 22 北京 技术 16000.0 2022
=== 北京或上海 ===
姓名 年龄 城市 部门 薪资 入职年份
0 张三 25 北京 技术 15000.0 2020
1 李四 30 上海 市场 20000.0 2019
4 钱七 22 北京 技术 16000.0 2022
5 孙八 40 上海 财务 NaN 2015
=== 年龄25-35 ===
姓名 年龄 城市 部门 薪资 入职年份
0 张三 25 北京 技术 15000.0 2020
1 李四 30 上海 市场 20000.0 2019
2 王五 28 广州 技术 18000.0 2021
3 赵六 35 深圳 人事 25000.0 2018示例3:多条件组合筛选
代码示例
# 技术部门且薪资大于16000
print("=== 技术部门 AND 薪资>16000 ===")
mask = (df['部门'] == '技术') & (df['薪资'] > 16000)
print(df[mask])
# 年龄小于25或大于35
print("\n=== 年龄<25 OR 年龄>35 ===")
print(df[(df['年龄'] < 25) | (df['年龄'] > 35)])
# 非技术部门
print("\n=== 非技术部门 ===")
print(df[~(df['部门'] == '技术')])
# 使用query
print("\n=== query方法 ===")
print(df.query('年龄 >= 25 and 城市 == "北京"'))输出:
代码示例
=== 技术部门 AND 薪资>16000 ===
姓名 年龄 城市 部门 薪资 入职年份
2 王五 28 广州 技术 18000.0 2021
=== 年龄<25 OR 年龄>35 ===
姓名 年龄 城市 部门 薪资 入职年份
4 钱七 22 北京 技术 16000.0 2022
5 孙八 40 上海 财务 NaN 2015
=== 非技术部门 ===
姓名 年龄 城市 部门 薪资 入职年份
1 李四 30 上海 市场 20000.0 2019
3 赵六 35 深圳 人事 25000.0 2018
5 孙八 40 上海 财务 NaN 2015
=== query方法 ===
姓名 年龄 城市 部门 薪资 入职年份
0 张三 25 北京 技术 15000.0 2020示例4:缺失值和重复值筛选
代码示例
# 筛选薪资缺失的行
print("=== 薪资缺失 ===")
print(df[df['薪资'].isnull()])
# 筛选薪资非缺失的行
print("\n=== 薪资非缺失 ===")
print(df[df['薪资'].notnull()])
# 使用query筛选缺失值
print("\n=== query筛选缺失值 ===")
print(df.query('薪资 != 薪资')) # NaN != NaN 为 True
# 按城市筛选重复
print("\n=== 重复的城市 ===")
print(df[df.duplicated('城市', keep=False)])六、实际应用场景
-
异常值检测:筛选超出正常范围的数据进行审查或处理
-
客户分群:根据消费金额、频率等条件筛选不同层级的客户
-
时间筛选:筛选特定时间段内的交易记录或日志数据
-
数据清洗:筛选缺失值、重复值、格式异常的数据进行清理
七、注意事项
注意1:多条件组合时,每个条件必须用括号括起来,且使用
&、|、~位运算符,而不是 and、or、not。
注意2:筛选返回的是视图或拷贝,直接修改可能触发 SettingWithCopyWarning。如果需要修改,建议先使用
.copy()创建副本。
注意3:NaN(缺失值)在比较运算中始终返回 False。例如
df[df['薪资'] > 0]会自动排除薪资为 NaN 的行。
小贴士
对于复杂的筛选条件,可以先将布尔条件赋值给变量,提高代码可读性。例如:
is_tech = df['部门'] == '技术'
high_salary = df['薪资'] > 20000
result = df[is_tech & high_salary]
八、筛选方法对比
九、小结
-
基本筛选使用布尔索引:df[df['列'] > 值]
-
多条件组合使用 &(与)、|(或)、~(非),每个条件需加括号
-
query() 提供更简洁的筛选语法,适合复杂条件
-
isin()、between()、str.contains() 是常用的高级筛选方法
-
筛选修改数据时注意 SettingWithCopyWarning 警告
十、练习题
练习1
创建一个包含10条产品记录的DataFrame(产品名、类别、价格、销量、评分),筛选出:价格在100-500元之间、销量大于100、评分大于4.0的产品。
练习2
使用 query() 方法重写练习1的筛选条件,对比两种方式的代码可读性。
练习3
创建一个包含姓名(中文)和邮箱的DataFrame,使用 str.contains() 和正则表达式筛选出邮箱域名是 gmail.com 或 outlook.com 的用户。
常见问题
为什么不能用 and/or 而要用 &/|?
因为 df['列'] > 值 返回的是布尔 Series(数组),Python 的 and/or 无法处理数组级的逻辑运算。& 和 | 是逐元素的位运算符,可以对数组中的每个元素进行逻辑运算。
筛选后如何修改原DataFrame?
使用 loc 可以避免警告:df.loc[df['条件'], '列名'] = 新值。或者先创建副本:filtered = df[df['条件']].copy(),然后修改 filtered。
query() 和布尔索引哪个性能更好?
对于大数据集,query() 通常更快,因为它内部使用了 numexpr 优化引擎。对于小数据集,两者差异不明显。query() 的优势在于代码可读性。
如何筛选包含空字符串的行?
空字符串 '' 不等于 NaN。筛选空字符串:df[df['列'] == ''] 或 df[df['列'].str.len() == 0]。同时筛选空字符串和NaN:df[(df['列'] == '') | df['列'].isnull()]。
本文涉及AI创作
内容由AI创作,请仔细甄别