

大家好,我是正在实战各种AI项目的程序员晚枫。
今天学习Pandas数据筛选与查询,这是数据分析最频繁的操作。
掌握这5种方法,无论数据量多大,你都能快速找到想要的数据。这些技巧在项目1:销售数据分析报表自动化中会大量使用。
准备数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| import pandas as pd import numpy as np
np.random.seed(42)
dates = pd.date_range(start='2024-01-01', periods=30, freq='D')
data = [] for date in dates: n_orders = np.random.randint(5, 15) for _ in range(n_orders): data.append({ '订单ID': f"ORD{np.random.randint(100000, 999999)}", '日期': date, '产品类别': np.random.choice(['电子产品', '服装', '食品', '家居']), '产品名称': np.random.choice(['iPhone', 'T恤', '零食', '杯子', '耳机', '鞋子']), '单价': np.random.randint(50, 5000), '数量': np.random.randint(1, 5), '地区': np.random.choice(['华北', '华东', '华南', '西南']), '销售员': np.random.choice(['张三', '李四', '王五', '赵六', '钱七']) })
df = pd.DataFrame(data) df['金额'] = df['单价'] * df['数量']
print(f"数据集大小: {len(df)} 条销售记录") print("\n前5行数据:") print(df.head())
|
方法1:布尔索引(最常用)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| high_value = df[df['金额'] > 1000] print(f"高价值订单: {len(high_value)} 条")
tech_high = df[(df['产品类别'] == '电子产品') & (df['金额'] > 2000)]
north_east = df[(df['地区'] == '华北') | (df['地区'] == '华东')]
not_food = df[~(df['产品类别'] == '食品')]
print("高价值订单示例:") print(high_value[['订单ID', '产品名称', '金额']].head())
|
方法2:isin - 多值匹配
1 2 3 4 5 6 7 8 9 10 11
| selected_categories = df[df['产品类别'].isin(['电子产品', '家居'])]
hot_regions = df[df['地区'].isin(['华北', '华东', '华南'])]
not_southwest = df[~df['地区'].isin(['西南'])]
print(f"选中类别订单数: {len(selected_categories)}") print(f"热门地区订单数: {len(hot_regions)}")
|
方法3:query - 类SQL语法
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| result = df.query('金额 > 1000')
result = df.query('产品类别 == "电子产品" and 金额 > 2000')
min_amount = 1500 result = df.query('金额 > @min_amount')
result = df.query('订单ID.str.contains("123")', engine='python')
print(f"Query筛选结果: {len(result)} 条")
|
优点:代码可读性更好,特别是复杂条件时。
方法4:loc - 标签索引
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| df_indexed = df.set_index('订单ID')
print("单个订单详情:") print(df_indexed.iloc[0])
print("\n前3个订单:") print(df_indexed.iloc[0:3])
print("\n指定列:") print(df_indexed.iloc[0:5][['产品名称', '金额']])
print("\n高价值订单的产品和地区:") print(df_indexed.loc[df_indexed['金额'] > 2000, ['产品类别', '地区', '金额']].head())
|
方法5:iloc - 位置索引
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| print("第1条记录:") print(df.iloc[0])
print("\n前5条记录:") print(df.iloc[0:5])
print("\n第1、3、5条记录:") print(df.iloc[[0, 2, 4]])
print("\n前10行前4列:") print(df.iloc[0:10, 0:4])
print("\n最后3条记录:") print(df.iloc[-3:])
|
字符串匹配筛选
1 2 3 4 5 6 7 8 9 10 11
| iphone_orders = df[df['产品名称'].str.contains('iPhone', na=False)]
ord_orders = df[df['订单ID'].str.startswith('ORD1', na=False)]
pattern_orders = df[df['订单ID'].str.match(r'ORD234.*', na=False)]
print(f"iPhone订单数: {len(iphone_orders)}") print(f"ORD1开头订单数: {len(ord_orders)}")
|
日期筛选
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| day_orders = df[df['日期'] == '2024-01-15']
df['月份'] = df['日期'].dt.month jan_orders = df[df['月份'] == 1]
range_orders = df[(df['日期'] >= '2024-01-10') & (df['日期'] <= '2024-01-20')]
from datetime import datetime, timedelta recent = df[df['日期'] >= df['日期'].max() - timedelta(days=7)]
print(f"1月订单数: {len(jan_orders)}") print(f"日期范围内订单数: {len(range_orders)}") print(f"最近7天订单数: {len(recent)}")
|
高效技巧
1. 链式操作
1 2 3 4 5 6 7 8 9 10 11 12
| filtered = df[df['产品类别'] == '电子产品'] result = filtered[filtered['金额'] > 2000] result = result.sort_values('金额', ascending=False)
result = (df[df['产品类别'] == '电子产品'] .query('金额 > 2000') .sort_values('金额', ascending=False))
print("链式操作结果:") print(result[['产品名称', '金额', '地区']].head())
|
2. 使用copy避免警告
1 2 3 4 5 6 7
| subset = df[df['产品类别'] == '电子产品'] subset['折扣'] = 0.9
subset = df[df['产品类别'] == '电子产品'].copy() subset['折扣'] = 0.9
|
3. 重置索引
1 2 3 4 5 6 7
| filtered = df[df['金额'] > 2000] print(f"原索引: {list(filtered.index[:5])}")
filtered = filtered.reset_index(drop=True) print(f"新索引: {list(filtered.index[:5])}")
|
实战:销售数据复杂筛选场景
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
|
high_value_orders = ( df[ (df['地区'] == '华东') & (df['产品类别'] == '电子产品') & (df['金额'] > 3000) & (df['销售员'].isin(['张三', '李四'])) ] .sort_values('金额', ascending=False) .reset_index(drop=True) )
print(f"符合条件的高价值订单: {len(high_value_orders)} 条") print("\n订单详情:") print(high_value_orders[['订单ID', '产品名称', '金额', '销售员', '日期']])
total_amount = high_value_orders['金额'].sum() print(f"\n这些订单总金额: ¥{total_amount:,.0f}")
sales_by_person = high_value_orders.groupby('销售员').agg({ '订单ID': 'count', '金额': 'sum' }).rename(columns={'订单ID': '订单数'}) print("\n按销售员统计:") print(sales_by_person)
|
性能对比:不同筛选方式的速度
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import pandas as pd import numpy as np
df = pd.DataFrame({ 'id': range(100000), 'city': np.random.choice(['北京', '上海', '广州', '深圳'], 100000), 'age': np.random.randint(18, 65, 100000), 'salary': np.random.randint(5000, 30000, 100000), 'dept': np.random.choice(['技术', '市场', '财务', '运营'], 100000) })
%timeit df[(df['age'] > 30) & (df['salary'] > 15000)]
%timeit df.query('age > 30 & salary > 15000')
%timeit df.loc[(df['age'] > 30) & (df['salary'] > 15000)]
|
进阶用法
query高级用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| min_salary = 15000 target_cities = ['北京', '上海'] result = df.query('salary > @min_salary and city in @target_cities')
result = df.query('city.str.startswith("北")')
df_idx = df.set_index('city') result = df_idx.query('index == "北京"')
result = df.query('(age > 30 & salary > 15000) | (dept == "技术" & age < 25)')
|
where和mask
1 2 3 4 5 6 7 8 9
| df['salary'].where(df['salary'] > 10000, other='低薪')
df['salary'].mask(df['salary'] < 10000, other='低薪')
df['salary_level'] = df['salary'].where(df['salary'] >= 20000, '一般') df['salary_level'] = df['salary_level'].where(df['salary'] >= 20000, '低薪')
|
isin多值匹配
1 2 3 4 5 6 7 8 9 10
| target_cities = ['北京', '上海', '深圳'] result = df[df['city'].isin(target_cities)]
result = df[~df['city'].isin(target_cities)]
city_region = {'北京': '华北', '上海': '华东', '广州': '华南', '深圳': '华南'} df['region'] = df['city'].map(city_region)
|
避坑指南
❌ 坑1:链式布尔条件忘记括号
1 2 3 4 5
| result = df[df['age'] > 30 & df['salary'] > 15000]
result = df[(df['age'] > 30) & (df['salary'] > 15000)]
|
❌ 坑2:str方法遇到NaN
1 2 3 4 5
| df['city'].str.contains('北')
df['city'].str.contains('北', na=False)
|
实战案例:HR部门筛选候选人
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| import pandas as pd import numpy as np
np.random.seed(42) n = 5000 df = pd.DataFrame({ 'name': [f'候选人{i:04d}' for i in range(n)], 'age': np.random.randint(22, 50, n), 'education': np.random.choice(['本科', '硕士', '博士'], n, p=[0.6, 0.3, 0.1]), 'experience': np.random.randint(0, 20, n), 'expected_salary': np.random.randint(8000, 35000, n), 'skill_score': np.random.uniform(40, 100, n).round(1), 'city': np.random.choice(['北京', '上海', '广州', '深圳', '成都', '重庆', '杭州'], n) })
candidates = df.query( 'skill_score > 75 and expected_salary < 25000 ' 'and 3 <= experience <= 10 ' 'and city in ["北京", "上海", "深圳", "杭州"]' )
print(f"符合条件的候选人: {len(candidates)} 人") print(f"\n候选人概览:") print(candidates[['name', 'age', 'education', 'experience', 'skill_score', 'expected_salary', 'city']].head(10))
top10 = candidates.nlargest(10, 'skill_score') print(f"\nTop 10候选人:") print(top10[['name', 'skill_score', 'expected_salary']])
|
多表关联筛选
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| orders = pd.DataFrame({ 'order_id': [1, 2, 3, 4, 5], 'user_id': [101, 102, 103, 104, 105], 'amount': [500, 300, 800, 200, 1000] })
vip_users = pd.DataFrame({ 'user_id': [101, 103, 105], 'vip_level': [3, 2, 3] })
vip_orders = orders[orders['user_id'].isin(vip_users['user_id'])]
vip_orders = orders.merge(vip_users, on='user_id')
vip_orders = orders.set_index('user_id').join(vip_users.set_index('user_id'), how='inner')
|
nlargest和nsmallest
1 2 3 4 5 6
| df.nlargest(10, 'salary') df.nsmallest(5, 'age')
df.nlargest(10, ['salary', 'age'])
|
按数据类型筛选列
1 2 3 4 5 6 7 8 9 10 11
| numeric_cols = df.select_dtypes(include=['int64', 'float64'])
str_cols = df.select_dtypes(include=['object'])
exclude_date = df.select_dtypes(exclude=['datetime64'])
cat_cols = df.select_dtypes(include=['category'])
|
多条件筛选速查
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| df[(df['age'] > 30) & (df['city'] == '北京')]
df[(df['city'] == '北京') | (df['city'] == '上海')]
df[df['city'].isin(['北京', '上海', '深圳'])]
df[~df['city'].isin(['北京', '上海'])]
df[df['age'].between(25, 35)]
df[df['name'].str.contains('张')]
df[df['email'].str.match(r'^[\w.]+@company\.com$')]
df[df['email'].isna()] df[df['email'].notna()]
df.query('age > 30 and city in ["北京", "上海"]') df.query('25 <= age <= 35')
|
筛选后操作的常见模式
1 2 3 4 5 6 7 8 9 10 11
| df.loc[df['age'] > 60, 'status'] = '退休'
df[df['city'] == '北京']['salary'].describe()
df[df['year'] == 2025].nlargest(10, 'salary')
df[df['status'] == 'active'].groupby('city').size()
|
下节预告
下一课我们将学习数据清洗-处理缺失值,这是数据分析中最重要的环节。干净的输入才有可靠的输出。
👉 继续阅读:Pandas数据清洗-处理缺失值
💬 加入学习交流群
扫码加入Python学习交流群,和数千名同学一起进步:
👉 点击加入交流群
群里不定期分享:
- 数据分析实战案例
- Python学习资料
- 求职面试经验
- 行业最新动态
推荐:AI Python数据分析实战营
🎁 限时福利:送《利用Python进行数据分析》实体书
👉 点击了解详情
课程导航
上一篇: Pandas数据读取与保存
下一篇: Pandas数据清洗-处理缺失值
PS:数据筛选是日常工作中最高频的操作。熟练掌握这5种方法,效率提升10倍。这些技巧在项目1的销售报表自动化中会大量用到。
📚 推荐教材
主教材:《Excel+Python 飞速搞定数据分析与处理(图灵出品)》
💬 联系我
主营业务:AI 编程培训、企业内训、技术咨询
🎓 AI 编程实战课程
想系统学习 AI 编程?程序员晚枫的 AI 编程实战课 帮你从零上手!