☰
09_筛选归类
2026/10/7 16:29:32 网站建设 项目流程

分组统计告诉你"每类花了多少",但有时候你想更细——“吃饭里超过50的有几笔?”“周末花了多少?”“备注含’聚餐’的有哪些?”"小额中额大额各几笔?"这些全是筛选的问题。

拿到数据,90%的时间你不是全量分析,而是先"捞"出关心的部分再处理。今天把最常用的8 个筛选场景整理成手册,每个直接给代码和解释。

用的还是账单数据,先放这里做对照:

importpandasaspdimportnumpyasnp data={'日期':['2024-01-05','2024-01-06','2024-01-07','2024-01-08','2024-01-09'],'类别':['餐饮','交通','餐饮','购物','餐饮'],'金额':[35.5,12.0,128.0,256.0,68.0],'备注':['午餐','地铁','聚餐','衣服','晚饭']}df=pd.DataFrame(data)

场景1:按数值大小筛选

找出金额大于100的消费:

result=df[df['金额']>100]

方括号里的df['金额'] > 100返回一列 True/False(布尔索引),Pandas 自动留下 True 的行。比较运算符><>=<===!=都能用。后面所有高级筛选本质上都是在构造不同的布尔条件。


场景2:多个条件叠加

且(同时满足)用&:金额大于100 并且 类别是餐饮。

result=df[(df['金额']>100)&(df['类别']=='餐饮')]

或(满足一个就行)用|:金额大于200 或者 类别是交通。

result=df[(df['金额']>200)|(df['类别']=='交通')]

非(取反)用~:类别不是餐饮。

result=df[~(df['类别']=='餐饮')]

⚠️ 每个条件都要用括号包起来,否则运算符优先级会让结果全错。也不要用and/or,整列逐元素运算要用&/|。


场景3:从列表里挑

类别是餐饮、交通、购物中的任意一个,用isin()比写一堆|优雅:

result=df[df['类别'].isin(['餐饮','交通','购物'])]

"不在列表里"前面加~:

result=df[~df['类别'].isin(['餐饮','交通'])]

筛选类别、地区、状态这类离散值时特别好用。


场景4:按文本模糊查找

Pandas 的str系列方法干这个。备注里包含"餐"字:

result=df[df['备注'].str.contains('餐')]

开头结尾匹配:

df[df['备注'].str.startswith('午')]# 以"午"开头df[df['备注'].str.endswith('餐')]# 以"餐"结尾

⚠️ 数据里有 NaN 时,str.contains会返回 NaN 导致多出奇怪的行,加na=False就安全了:

df[df['备注'].str.contains('聚餐',na=False)]

场景5:按日期范围筛选

先把日期列转成 datetime:

df['日期']=pd.to_datetime(df['日期'])

直接比较:

result=df[(df['日期']>='2024-01-05')&(df['日期']<='2024-01-07')]

把日期设为索引后切片更优雅:

df_date=df.set_index('日期')print(df_date['2024-01'])# 整个1月print(df_date['2024-01-05':'2024-01-08'])# 一段时间

按星期筛选(周六=5,周日=6):

df['是周末']=df['日期'].dt.dayofweek>=5weekend_spend=df[df['是周末']]['金额'].sum()

转成 datetime 后,.dt.year.dt.month.dt.day.dt.dayofweek这些属性随便用。


场景6:用 loc 既筛选行又选列

只看满足条件行的其中几列:

result=df.loc[df['金额']>100,['类别','金额']]

格式是df.loc[行条件, 列条件]。loc 最大的好处是可以赋值,比如给大额消费加标记列:

df.loc[df['金额']>100,'大额消费']='是'df.loc[df['金额']<=100,'大额消费']='否'

这个在数据清洗和特征工程里经常用。(iloc按位置数字选,日常 95% 场景用 loc 就够了。)


场景7:分箱归类——把连续数据分成档

想看消费档次分布(小额/中额/大额各多少笔),用pd.cut():

bins=[0,50,200,float('inf')]labels=['小额(0-50)','中额(50-200)','大额(200+)']df['消费档次']=pd.cut(df['金额'],bins=bins,labels=labels)

分箱完再 groupby,分布就出来了:

result=df.groupby('消费档次').agg(笔数=('金额','count'),总金额=('金额','sum'))

n 个边界分成 n-1 个区间;默认左开右闭,right=False可改;float('inf')接住最大值以上。


场景8:实战——拿完整账单回答4个问题

先造一份31天的模拟数据:

np.random.seed(42)dates=pd.date_range('2024-01-01','2024-01-31',freq='D')categories=['餐饮','交通','购物','娱乐','居住','医疗']bills=[]fordindates:for_inrange(np.random.randint(1,5)):cat=np.random.choice(categories)ifcat=='居住':amount=round(np.random.uniform(800,2500),2)elifcat=='医疗':amount=round(np.random.uniform(50,500),2)elifcat=='购物':amount=round(np.random.uniform(30,800),2)else:amount=round(np.random.uniform(10,200),2)bills.append({'日期':d,'类别':cat,'金额':amount})df=pd.DataFrame(bills)df['日期']=pd.to_datetime(df['日期'])

四个问题,全用今天讲的筛选技巧:

# Q1:这个月吃饭花了多少?food_total=df[df['类别']=='餐饮']['金额'].sum()# Q2:单笔超过200的有几笔?big_count=len(df[df['金额']>200])# Q3:周末消费占比多少?df['是周末']=df['日期'].dt.dayofweek>=5weekend_ratio=df[df['是周末']]['金额'].sum()/df['金额'].sum()*100# Q4:大额消费(>100)集中在哪些类别?big=df[df['金额']>100]result=big.groupby('类别')['金额'].agg(['count','sum']).sort_values('sum',ascending=False)

布尔索引、条件组合、日期属性、筛选后分组——组合起来就能回答绝大多数业务问题。


真实运行效果

把上面 8 个场景在同一份账单数据上实际跑一遍,输出是这样的:

可以看到:数值筛选只留下 128.0、256.0 两行,& 条件精确命中餐饮大额,isin 一次捞回三类,str.contains 按备注模糊匹配,日期切片连续取出 5 到 8 号;31 天 85 笔的实战里,餐饮共花 2120.08、周末占比 24.2%,大额消费按类别汇总居住最多。


新手常见坑

  1. 多条件忘了加括号→ 每个条件用括号包起来
  2. 用 and/or 而不是 &/|→ 整列运算要用位运算符
  3. 筛选后索引乱了→ 用.reset_index(drop=True)重置

一张表总结8个场景

场景核心写法
按数值大小df[df['列'] > 值]
多条件组合(条件1) & (条件2)
列表匹配df[df['列'].isin([...])]
文本模糊搜索df['列'].str.contains('关键词')
日期范围(df['日期'] >= start) & (df['日期'] <= end)
选行又选列df.loc[行条件, 列列表]
连续数据分档pd.cut(数据, bins, labels)
筛选后分析先筛选,再 groupby

下一篇讲结果导出——分析完的数据怎么导出成规整的 Excel 报表、多 Sheet 管理、透视表生成。


梅雅达编程工作室 · Python数据实战系列第9篇
筛选说到底就是构造条件,条件会写了,几万条数据里捞想要的那几条,就是一行代码的事。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询