You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中带条件的GroupBy与违规分类问题求助

解决思路:分组统计格式优化与违规分类实现

嗨,我来帮你一步步搞定这两个问题,先从分组统计的格式调整说起,再处理违规分类的逻辑~

一、分组统计:实现目标显示格式

你用df.groupby(['name', 'id']).size().reset_index(name='counts')其实已经得到了正确的统计结果,只是显示格式不符合预期。要注意的是:DataFrame本身的存储结构里每一行的name列都有值,你想要的“同一个name只显示第一行”是可视化/输出层面的格式,我们可以通过两种方式实现:

方式1:仅用于显示的样式设置(适合Notebook展示)

如果只是在Jupyter Notebook里想让表格更易读,可以用pandas的Styler隐藏重复的name值:

import pandas as pd

# 先完成基础分组统计
df_counts = df.groupby(['name', 'id'], as_index=False).size().rename(columns={'size': 'count'})

# 设置样式,把重复的name单元格隐藏
styled_table = df_counts.style.hide(axis='index').set_table_styles([
    {'selector': 'tr:not(:first-child) td:first-child',
     'props': [('visibility', 'hidden')]}
])

# 展示样式化后的表格
display(styled_table)

方式2:生成带空值的DataFrame(适合导出Excel等)

如果需要把重复name的位置设为空字符串(比如导出到Excel时保持格式),可以先排序,再用shift判断是否和前一行name相同:

df_counts = df.groupby(['name', 'id'], as_index=False).size().rename(columns={'size': 'count'})
# 按name排序,确保同一name的行连续排列
df_counts = df_counts.sort_values('name')
# 把和上一行重复的name替换为空字符串
df_counts['name'] = df_counts['name'].where(df_counts['name'] != df_counts['name'].shift(), '')

# 输出结果
print(df_counts)

这样得到的DataFrame就完全符合你期望的格式了。

二、违规分类:按规则判断

你的思路方向是对的,但需要先拿到每个name对应的90和91的计数,再按规则逐步判断。这里用pivot_table把计数转成列会更方便处理:

完整实现代码

import pandas as pd

# 第一步:获取每个name对应的90、91计数
pivot_df = df.pivot_table(
    index='name',
    columns='id',
    values='id',
    aggfunc='count',
    fill_value=0  # 把不存在的id计数设为0
).rename(columns={90: 'count_90', 91: 'count_91'})

# 第二步:编写违规判断逻辑
def check_violation(row):
    # 情况1:仅对应一个id(90或91),不属于违规
    if row['count_90'] == 0 or row['count_91'] == 0:
        return 0
    # 情况2:同时对应两个id
    else:
        # 子情况i:90计数<5且91计数>0,不属于违规
        if row['count_90'] < 5 and row['count_91'] > 0:
            return 0
        # 其他情况都属于违规
        else:
            return 1

# 应用判断函数到每一行
pivot_df['violation'] = pivot_df.apply(check_violation, axis=1)

# 提取最终需要的列
result_df = pivot_df[['violation']].reset_index()

# 输出结果
print(result_df)

简化版(用numpy链式判断)

如果想让代码更简洁,可以用np.where替代自定义函数:

import pandas as pd
import numpy as np

pivot_df = df.pivot_table(
    index='name',
    columns='id',
    values='id',
    aggfunc='count',
    fill_value=0
).rename(columns={90: 'c90', 91: 'c91'})

# 用np.where嵌套实现多条件判断
pivot_df['violation'] = np.where(
    # 仅一个id的情况,返回0
    (pivot_df['c90'] == 0) | (pivot_df['c91'] == 0),
    0,
    # 两个id的情况,再判断是否符合非违规条件
    np.where(
        (pivot_df['c90'] < 5) & (pivot_df['c91'] > 0),
        0,
        1
    )
)

result_df = pivot_df[['violation']].reset_index()

这样就能完美得到你想要的违规分类结果啦!

内容的提问来源于stack exchange,提问作者user13419531

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:25:39