如何按时间顺序遍历DataFrame列并基于其他列生成输出列C?
解决Pandas DataFrame按指定逻辑生成计数列的问题
输入与期望输出
输入DataFrame
import pandas as pd df = pd.DataFrame({ 'A': ['a', 'b', 'c', 'c', 'a', 'b', 'c', 'd', 'a', 'b', 'c', 'c', 'a', 'b', 'c'], 'B': ['Good', 'Good', 'Good', 'Good', 'Good', 'Bad', 'Good', 'Good', 'Good', 'Good', 'Bad', 'Good', 'Good', 'Good', 'Good'] })
期望输出DataFrame
A B C 0 a Good 1 1 b Good 1 2 c Good 1 3 c Good 1 4 a Good 1 5 b Bad 1 6 c Good 1 7 d Good 1 8 a Good 2 9 b Good 2 10 c Bad 2 11 c Good 2 12 a Good 3 13 b Good 3 14 c Good 3
核心逻辑
- 初始计数
n=1 - 当B列值不为
Good时:- 若A列是
c或d,保持当前计数n,直到遇到A列非c/d的行时,再将n+1 - 若A列不是
c或d,直接将n+1,后续行使用新的计数
- 若A列是
- B列值为
Good时,保持当前计数n不变
解决方案(高效向量化实现)
import pandas as pd # 构造输入数据 df = pd.DataFrame({ 'A': ['a', 'b', 'c', 'c', 'a', 'b', 'c', 'd', 'a', 'b', 'c', 'c', 'a', 'b', 'c'], 'B': ['Good', 'Good', 'Good', 'Good', 'Good', 'Bad', 'Good', 'Good', 'Good', 'Good', 'Bad', 'Good', 'Good', 'Good', 'Good'] }) # 1. 标记所有B≠Good的触发行 trigger = df['B'] != 'Good' # 2. 标记所有A不是c/d的行 non_cd = ~df['A'].isin(['c', 'd']) # 3. 处理延迟触发:标记需要延迟传递的触发点 pending_trigger = trigger & ~non_cd # 累计延迟触发的数量,用于追踪待处理的计数需求 temp = pending_trigger.cumsum() # 4. 生成有效触发点: # - 原本不需要延迟的触发(B≠Good且A非c/d) # - 延迟触发后遇到的第一个非c/d行(此时处理之前的计数需求) valid_trigger = (temp.diff() != 0) & non_cd valid_trigger |= trigger & non_cd # 5. 计算最终计数列,初始值为1 df['C'] = valid_trigger.cumsum() + 1 # 查看结果 print(df)
代码解释
- 标记触发行:用
trigger列记录所有B列不是Good的行,这些是潜在的计数触发点。 - 标记非c/d行:用
non_cd列区分A列是否为c或d,用于判断是否需要延迟计数。 - 追踪延迟触发:
pending_trigger标记需要延迟的触发点,temp累计这些点的数量,确保能追踪到待处理的计数需求。 - 生成有效触发点:
(temp.diff() != 0) & non_cd:当遇到非c/d行且累计延迟触发数有变化时,说明需要处理之前的延迟计数需求,标记为有效触发点。trigger & non_cd:直接标记不需要延迟的触发点。
- 计算计数:对有效触发点做累计求和,再加1得到初始计数1,最终生成C列。
内容的提问来源于stack exchange,提问作者Jimmy Vo
相关产品推荐
相关产品推荐

