如何在Pandas中按多条件删除DataFrame行?
解决Pandas中删除多条件匹配行的逻辑错误问题
先看一下你给出的原始DataFrame:
import pandas as pd df = pd.DataFrame({ 'case_id': [1050, 1050, 1050, 1050, 1051, 1051, 1051, 1051], 'elm_id': [101, 102, 101, 102, 101, 102, 101, 102], 'cid': [1, 1, 2, 2, 1, 1, 2, 2], 'fx': [736.1, 16.5, 98.8, 158.5, 272.5, 750.0, 333.4, 104.2], 'fy': [992.0, 261.3, 798.3, 452.0, 535.9, 838.8, 526.7, 119.4], 'fz': [428.4, 611.0, 948.3, 523.9, 880.9, 340.3, 890.7, 422.1] })
你的需求是删除case_id属于cases = [1051]且cid属于ids = [1]的行,也就是只删掉case_id=1051且cid=1的那两行,保留剩下的6行。
为什么你的原有方法会得到相反结果?
你写的两个条件:
df2 = df[(df.case_id != 1051) & (df.cid != 1)] # 或者 df.query('(case_id != 1051) & (cid != 1)')
这里犯了一个逻辑错误:&表示同时满足两个条件,也就是筛选出“既不是case_id=1051,同时cid也不是1”的行。这会过滤掉:
- 所有case_id=1051的行(不管cid是什么)
- 所有cid=1的行(不管case_id是什么)
最后剩下的只有case_id=1050且cid=2的两行,完全和你的需求相反。
正确的解决方案
我们需要的逻辑是:排除那些同时满足case_id在cases列表且cid在ids列表的行,可以通过三种方式实现:
方法1:对联合条件取反
用~符号对“case_id匹配且cid匹配”的布尔数组取反,这是最直观的写法:
cases = [1051] ids = [1] df2 = df[~((df.case_id.isin(cases)) & (df.cid.isin(ids)))]
方法2:应用德摩根定律
根据逻辑运算的德摩根定律:非(A且B) = 非A 或 非B,我们可以把条件转化为“case_id不在cases列表,或者cid不在ids列表”,写法更灵活:
df2 = df[(~df.case_id.isin(cases)) | (~df.cid.isin(ids))]
方法3:使用query方法实现
如果习惯用query语法,同样可以套用上面的逻辑,代码更简洁易读:
df2 = df.query('not (case_id in @cases and cid in @ids)') # 或者等价的写法: df2 = df.query('case_id not in @cases or cid not in @ids')
验证结果
执行以上任意一种方法后,得到的df2就是你期望的6行数据:
case_id cid elm_id fx fy fz 0 1050 1 101 736.1 992.0 428.4 1 1050 1 102 16.5 261.3 611.0 2 1050 2 101 98.8 798.3 948.3 3 1050 2 102 158.5 452.0 523.9 6 1051 2 101 333.4 526.7 890.7 7 1051 2 102 104.2 119.4 422.1
内容的提问来源于stack exchange,提问作者twegner
相关产品推荐
相关产品推荐

