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

Python中如何按user_id分组后按规则筛选行并返回单条结果?

问题:DataFrame分组后按规则提取tier值

需求说明

对DataFrame按user_id分组后,每组仅返回一条tier结果,规则如下:

  • 若rank=1且tier≠Unknown,返回该tier(如用户a001)
  • 否则返回rank=2对应的tier(如用户b001)
  • 若rank=1且tier=Unknown,返回'no_tier'(如用户c001)

注:每个user_id的tier中Unknown仅出现一次。

原始DataFrame

user_id tier    rank
a001    High     1
a001    Low      2
a001    Unknown  3
b001    Unknown  1 
b001    Mid      2
c001    Unknown  1

预期结果

tier    
High     
Mid      
no_tier  

你的错误代码

def get_tier(x):
    if x['rank'] ==1 and x['tier'] != 'Unknown':
        return x['tier']
    elif x['rank'] == 2:
        return x['tier']
    else:
        return 'no_tier'

df.goupby('user_id').apply(lambda x : x.apply(get_tier), axis = 1).iloc[0]).reset_index()

错误点说明

  1. goupby拼写错误,正确应为groupby
  2. 分组后apply的逻辑错误:x是每个用户的子DataFrame,不是单行数据,嵌套的x.apply(get_tier, axis=1)会对每行调用函数,但最后取iloc[0]的逻辑混乱,无法得到每组唯一的结果。

正确解法

方法一:修正分组apply逻辑

重写函数处理每个用户的子DataFrame,按规则判断返回结果:

import pandas as pd

# 构造原始DataFrame
df = pd.DataFrame({
    'user_id': ['a001', 'a001', 'a001', 'b001', 'b001', 'c001'],
    'tier': ['High', 'Low', 'Unknown', 'Unknown', 'Mid', 'Unknown'],
    'rank': [1, 2, 3, 1, 2, 1]
})

def get_tier(group):
    # 获取当前用户rank=1的行
    rank1_row = group[group['rank'] == 1].iloc[0]
    if rank1_row['tier'] != 'Unknown':
        return rank1_row['tier']
    # 检查是否存在rank=2的行
    rank2_rows = group[group['rank'] == 2]
    if not rank2_rows.empty:
        return rank2_rows.iloc[0]['tier']
    # 对应rank=1且tier=Unknown的情况
    return 'no_tier'

# 分组应用函数,得到结果
result = df.groupby('user_id').apply(get_tier).reset_index(name='tier')
# 若仅需要tier列,可执行以下操作
result = result['tier']
print(result)

输出结果:

0       High
1        Mid
2    no_tier
Name: tier, dtype: object

方法二:高效筛选法(适合大数据量)

通过排序和优先级标记,避免循环式apply,提升效率:

import pandas as pd

df = pd.DataFrame({
    'user_id': ['a001', 'a001', 'a001', 'b001', 'b001', 'c001'],
    'tier': ['High', 'Low', 'Unknown', 'Unknown', 'Mid', 'Unknown'],
    'rank': [1, 2, 3, 1, 2, 1]
})

# 按用户和rank升序排序,确保rank小的行在前
df_sorted = df.sort_values(['user_id', 'rank'])

# 给每行标记优先级:规则1优先级最高,规则2次之,规则3最低
df_sorted['priority'] = 0
df_sorted.loc[(df_sorted['rank'] == 1) & (df_sorted['tier'] != 'Unknown'), 'priority'] = 3
df_sorted.loc[df_sorted['rank'] == 2, 'priority'] = 2
df_sorted.loc[(df_sorted['rank'] == 1) & (df_sorted['tier'] == 'Unknown'), 'priority'] = 1

# 每组取优先级最高的行的tier值
result = df_sorted.groupby('user_id').apply(lambda x: x.loc[x['priority'].idxmax(), 'tier']).reset_index(name='tier')
result = result['tier']
print(result)

输出结果和方法一一致。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 07:00:56