drop(index=...) 是精确删除,按索引标签或位置删,不依赖数据内容;布尔索引如 df[(df['score']>18) & (df['city'].isin(['北京','上海']))] 才是条件过滤;dropna() 和 drop_duplicates() 是语义化特化删除,更稳更简。

drop(index=...) 是精确删除,不是条件过滤
drop() 的本质是“按索引标签或位置删”,它不看数据内容,只认 index 值或整数位置。哪怕某行满足业务条件(比如“销售额 drop() 就完全无视。
- 常见错误:写
df.drop(df[df['sales'] —— 这看似在“条件删除”,实则仍是先用布尔索引找出索引,再交给 <code>drop()执行,属于“两步走”,不是drop()自身支持条件 - 真正适合
drop(index=...)的场景:清理已知脏索引(如'temp_row_999')、删除测试插入的临时行、按日志记录的 ID 批量下线数据 - 性能注意:如果
df.index是默认整数索引,drop(index=[0, 5, 100])很快;但若 index 是字符串且无序,Pandas 需哈希查找,大量删除时不如布尔索引直接切片
条件删除该用布尔索引,不是 drop()
真要按值删行(比如“删掉所有 status 为 'inactive' 的记录”),直接用布尔索引最自然、最可读、也最快:
df = df[df['status'] != 'inactive']
- 为什么不用
drop()包裹?因为df.drop(df[df['status']=='inactive'].index)多一次中间索引提取,内存多占一份,还容易因重复索引出错(drop()遇重复 index 默认只删第一个) - 多个条件?用括号 +
&:df[(df['age'] > 18) & (df['city'].isin(['北京', '上海']))];别漏括号,否则运算符优先级错乱 - 想“原地删”?布尔索引本身不修改原
df,要覆盖就赋值;若坚持不新建变量,可用df.drop(..., inplace=True),但inplace=True在新版本 Pandas 中已逐步弃用,不推荐
dropna() 和 drop_duplicates() 是特化条件删除
这两类删除表面像“条件”,其实是 Pandas 内置的语义化操作,底层优化过,比手写布尔逻辑更稳、更省心:
-
dropna(subset=['email']):删掉'email'列为空的行——比df[df['email'].notna()]略快,语义更直白;但若同时要检查多列非空,how='all'或thresh参数比嵌套notna()更简洁 -
drop_duplicates(subset=['user_id'], keep='last'):保留每个user_id最后一次出现的行——手写groupby().tail(1)也可,但慢且易错;drop_duplicates()是唯一正确解 - 坑点:默认
keep='first',但业务常要最新数据,别忘了显式写keep='last'
混合场景:先条件筛选,再 drop 索引
有些需求必须组合使用——比如“删掉所有重复 user_id 中,除了最新一条以外的、且 score
- 先用
duplicated(keep=False)标出所有重复项,再结合score条件筛出要删的子集 - 再用
drop()删除这批索引:to_drop = df[duplicated_mask & (df['score'] - 关键提醒:
drop()对索引敏感,如果中间有reset_index()或sort_values(),索引会变,务必确认to_drop对应的是当前df.index
最易被忽略的其实是索引一致性——删之前打印 len(df) 和 len(to_drop),再检查几个被删行的原始 index 值,比事后调试快十倍。









