Pandas按条件最大值填充列:标记每个ID首个已批准最大值行
问题:为DataFrame新增is_max列标记首个符合条件的最大值行
原始DataFrame数据:
id, time, value, approved 0, 0:00, 10, false 1, 0:01, 20, false 1, 0:02, 50, false 1, 0:03, 20, true 1, 0:04, 40, true 1, 0:05, 40, true 1, 0:06, 20, false 2, 0:07, 35, false 2, 0:08, 35, false 2, 0:09, 50, true 2, 0:10, 50, true
需求:新增is_max列,每个ID下首个满足approved为true的最大值行标记为true,其余为false,最终结果如下:
id, time, value, approved, is_max 0, 0:00, 10, false, false 1, 0:01, 20, false, false 1, 0:02, 50, false, false 1, 0:03, 20, true, false 1, 0:04, 40, true, true 1, 0:05, 40, true, false 1, 0:06, 20, false, false 2, 0:07, 35, false, false 2, 0:08, 35, false, false 2, 0:09, 50, true, true 2, 0:10, 50, true, false
你尝试的代码:
df['is_max'] = df['value'] == df.groupby(['id', df['approved']])['value'].transform('max').where(df['approved'])
问题:这段代码会把每个ID下所有符合approved=true的最大值行都标记为true,不符合只标记首个的要求。
解决方案
方法一:分步实现
- 计算每个ID下
approved=true的value最大值
筛选出approved=true的行,按id分组取value的最大值,得到每个ID对应的目标最大值。 - 定位每个ID下第一个符合条件的行
对每个ID,筛选出approved=true且value等于对应最大值的行,取其中第一行的索引。 - 初始化并设置
is_max列
先将is_max列全部设为false,再把第二步找到的索引对应的行设为true。
完整代码:
import pandas as pd # 加载数据(替换为你的数据路径或读取方式) df = pd.read_csv('https://pastebin.com/raw/Hqk9YjuR') # 步骤1:计算每个ID下approved=true的value最大值 max_values = df[df['approved'] == True].groupby('id')['value'].max() # 步骤2:收集每个ID下首个符合条件的行索引 target_indices = [] for id_val in max_values.index: subset = df[(df['id'] == id_val) & (df['approved'] == True) & (df['value'] == max_values[id_val])] if not subset.empty: target_indices.append(subset.index[0]) # 步骤3:设置is_max列 df['is_max'] = False df.loc[target_indices, 'is_max'] = True # 查看结果 print(df)
方法二:链式操作简化版
用更简洁的链式代码实现相同逻辑:
import pandas as pd df = pd.read_csv('https://pastebin.com/raw/Hqk9YjuR') # 生成初始mask:标记所有approved=true且value为对应ID最大值的行 mask = df['approved'] & (df['value'] == df.groupby('id')['value'].transform(lambda x: x[df['approved']].max())) # 对每个ID只保留第一个符合mask的行,其余设为False df['is_max'] = mask.groupby(df['id']).cummax().eq(1) & mask print(df)
逻辑说明:
- 先通过
mask筛选出所有潜在符合条件的行 - 用
cummax()对每个ID的mask行做累积最大值,再用eq(1)锁定第一个True的位置,最后和mask取交集,确保仅首个符合条件的行被标记为True
内容的提问来源于stack exchange,提问作者mwind
相关产品推荐
相关产品推荐

