Pandas DataFrame 多列字符串条件筛选:匹配大小写正负标签行
现有代码的两处核心问题
- 逻辑关系完全错误:你需要筛选的是「两标签同属正类」或者「两标签同属负类」的行,但代码中用逻辑与(
&)连接了两个互斥的判断条件,相当于要求某一行同时满足“两个标签都是P/p开头”和“两个标签都是N/n开头”,这种行在数据中根本不存在。 - Pandas语法规则错误:Pandas的逐元素布尔运算不能使用Python原生的
and关键字,直接对两个布尔Series用and判断,会触发The truth value of a Series is ambiguous报错,必须使用逐元素逻辑运算符&(与)、|(或),且每个独立的判断逻辑需要用括号包裹规避运算符优先级问题。
正确实现代码
方案1:贴合原有startswith判断的修改版本
直接修正逻辑关系,将互斥的正类判断、负类判断取或即可:
# 正类一致的判断:label_one以大写P开头,label_two以小写p开头 mask_pos = (df['label_one'].str.startswith('P')) & (df['label_two'].str.startswith('p')) # 负类一致的判断:label_one以大写N开头,label_two以小写n开头 mask_neg = (df['label_one'].str.startswith('N')) & (df['label_two'].str.startswith('n')) # 两个条件取或,筛选符合任意一类的行 ptp = df.loc[mask_pos | mask_neg]
方案2:鲁棒性更强的大小写归一化写法
考虑到标签本身只有大小写差异,直接统一转小写后做判断,能避免因为字符大小写格式不统一导致的匹配失效:
# 将两列标签统一转小写,消除大小写差异 pos_match = (df['label_one'].str.lower() == 'positive') & (df['label_two'].str.lower() == 'positive') neg_match = (df['label_one'].str.lower() == 'negative') & (df['label_two'].str.lower() == 'negative') ptp = df.loc[pos_match | neg_match]
方案3:最简洁的等价实现
在当前数据集的规则下,两列标签只要归一化后值相等,就必然属于同类别(要么同是正类,要么同是负类),可以直接简化判断:
# 归一化后两列值相等的行,就是标签一致的行 ptp = df.loc[df['label_one'].str.lower() == df['label_two'].str.lower()]
筛选结果说明
运行上述代码后,最终会保留6行符合要求的记录:
- 2017年文本为
yes it is的正类一致记录 - 2018年文本为
it has to be done的正类一致记录 - 2018年文本为
no的负类一致记录 - 2019年文本为
he is right的正类一致记录 - 2020年文本为
that is a trap的负类一致记录 - 2021年文本为
I am on my way的正类一致记录
内容的提问来源于stack exchange,提问作者Nate。
相关产品推荐
相关产品推荐

