不会出错,但逻辑易反:df[condition]是保留而非删除;删行需用~取反且注意括号优先级,如df[~(df['col']>5)];复杂条件建议先构造布尔序列;query()简洁但有列名和方法链限制;链式索引需.copy()避免视图问题。

用布尔索引直接赋值为空DataFrame会出错吗?
不会出错,但逻辑上容易反了——df[condition]是筛选保留,不是删除。想删行,得取反:用 ~(波浪号)对布尔数组取反,或者用 df.loc[~condition]。常见错误是写成 df = df[~df['col'] > 5] 却忘了括号优先级,实际执行成了 ~df['col'] > 5,结果全为 False,整表被清空。
正确写法必须加括号:df = df[~(df['col'] > 5)]。如果条件复杂,建议先构造布尔序列再使用:
mask = (df['age'] < 18) | (df['score'].isna()) df = df[~mask]
删除含空值、重复值或特定字符串的行怎么写?
这些都属于典型条件,但底层都是生成布尔序列。注意 isna() 和 isnull() 等价,但 == 'xxx' 对空值会返回 False(不是 NaN),所以不能靠等号捕获缺失;而 str.contains() 遇到 NaN 默认报错,得加 na=False 参数。
- 删空值行:
df = df[~df['name'].isna()]或df.dropna(subset=['name'], inplace=True)(后者更语义化) - 删重复行(按某列):
df = df[~df['id'].duplicated(keep='first')],keep='first'表示保留首次出现,其余删掉 - 删含“test”的行(忽略大小写+容错空值):
df = df[~df['desc'].str.contains('test', case=False, na=False)]
用query()方法比布尔索引更安全吗?
不一定更安全,但可读性高、不易错漏括号。query() 是字符串解析式,不涉及 Python 运算符优先级问题,比如 df.query("age > 18 and score > 90") 比 df[(df['age'] > 18) & (df['score'] > 90)] 少两个括号和一个 & 符号。但它有硬限制:
立即学习“Python免费学习笔记(深入)”;
- 列名含空格或特殊字符时必须用反引号:
df.query("`user id` > 100") - 不能直接调用方法链(如
.str.upper()),得提前算好新列或用engine='python'(性能下降) - 变量注入要用
@前缀:threshold = 85; df.query("score
小数据量下差异不大,但大数据集上 query() 底层用 numexpr 加速,有时反而更快。
原地修改inplace=True为什么经常失效?
因为多数布尔索引操作(如 df[~mask])本质是返回新 DataFrame,根本没触发 inplace 参数——它只在少数方法里有效,比如 drop()、fillna()、dropna()。想“原地删行”,别信 df[~mask].inplace=True,这句毫无作用;正确做法只有两种:
- 显式重新赋值:
df = df[~mask](推荐,明确、可控) - 用
drop()配合索引:df.drop(df[mask].index, inplace=True),但要注意mask为True表示要删的行,所以传的是df[mask].index
真正容易被忽略的是链式赋值警告(SettingWithCopyWarning)——当你从切片再做布尔索引时(如 sub_df = df[df['x']>0]; sub_df = sub_df[~sub_df['y'].isna()]),可能操作的是视图而非副本,后续修改行为不可控。最稳妥的方式始终是用 .copy() 显式切断引用。


















