Pandas分组后保留组内DisID最大值行的实现及报错修复
报错原因
触发TypeError: bad operand type for unary ~: 'str'的直接原因是代码逻辑写错:
- 变量
s是drop_duplicates()返回的DataFrame对象,不是布尔型的掩码数组。你写~s是尝试对整个DataFrame做按位取反操作,pandas会将这个操作广播到每一列的元素上,而表中存在字符串类型的列值,Python不支持对字符串做~取反运算,直接抛出类型错误。 - 除此之外原代码还有两处逻辑偏差:
- 按
DisseminationID(即示例中的DisID)升序排序后去重,默认保留第一条数据,拿到的是每组DisID最小的行,和你要保留组内DisID最大值行的需求相反。 - 取反删行的索引逻辑完全混乱,即使不报错也得不到正确结果。
- 按
正确实现方案
提供两种可直接运行的实现,都能满足需求:
方案1:排序+去重(逻辑直观、性能最优)
核心思路是先把DisID按降序排列,让每组DisID最大的行排在组内最前面,再按GroupID去重保留首行即可,不需要额外的索引取反、删行操作:
# 原有打分组标记的逻辑保持不变,注意列名和实际字段匹配 docsDF['GroupID'] = docsDF.groupby(['ExecutionTimestamp','Notional','Trade_type']).ngroup() # 按DisID降序排序,同组最大值排最前,按GroupID去重保留首行 result = docsDF.sort_values("DisseminationID", ascending=False).drop_duplicates(subset=['GroupID'], keep='first')
方案2:分组取极值索引(语义最贴合需求)
直接通过groupby取每组DisID最大值对应的行索引,再按索引提取数据即可:
# 原有打分组标记逻辑不变 docsDF['GroupID'] = docsDF.groupby(['ExecutionTimestamp','Notional','Trade_type']).ngroup() # 提取每个GroupID下DisID最大的行索引 max_idx = docsDF.groupby('GroupID')['DisseminationID'].idxmax() # 按索引取值得到结果 result = docsDF.loc[max_idx]
注意:如果DisID列存在空值,排序时可添加na_position='last'参数将空值排到末尾,避免取到空值行;idxmax方法默认会自动跳过空值。
用提供的示例数据测试,两种方案返回的结果完全符合预期:
| DisID | BunchData | GroupID |
|---|---|---|
| 1000 | xyz | 1 |
| 2014 | abc | 2 |
| 3000 | def | 3 |
内容的提问来源于stack exchange,提问作者keynesiancross
相关产品推荐
相关产品推荐

