如何使用Pandas按指定序列规则对DataFrame进行数值加减运算?
使用Pandas实现自定义序列规则的计算需求
问题背景
我有一个包含两列的DataFrame,数据如下:
import pandas as pd data = { 'value': [12506, 12501, 12513, 12513, 12521, 12501, 12583, 12594, 12598, 12589, 12615, 12615, 12611, 12573, 12593, 12564], 'Sequence': [-1, -2, -3, 1, 2, 3, -1, -2, 1, -1, 1, 2, 3, -1, -2, -3] } df = pd.DataFrame(data)
我希望按照以下序列规则计算得到一个新的DataFrame:
- 规则1:取标签为
-2对应的Value值与标签为-3对应的Value值,计算方式为:label(-3) - label(-2)(比如第一组的12513 - 12501 = -12) - 规则2:取标签为
2对应的Value值与标签为3对应的Value值,计算方式为:label(2) - label(3)(比如第二组的12521 - 12501 = 20) - 规则3:若标签为
(-2, 2)之后没有标签(-3,3),但存在标签(-1, 1),则计算:label(-2) - label(1)(比如第三组的12594 - 12598 = -4) - 规则4:若标签为
(-1,1)之后出现(1, -1),则不进行计算
期望得到的结果DataFrame如下:
Calculation 0 -12 1 20 2 -4 3 4 4 -29
请问是否可以使用Pandas实现上述需求?
解决方案:当然可以实现!
核心思路是先把数据按连续的序列组划分(因为你的规则都是针对一段连续序列来计算的),然后对每个组单独应用对应的规则就行。以下是完整的可运行代码,每一步都有详细解释:
import pandas as pd # 原始数据转成DataFrame data = { 'value': [12506, 12501, 12513, 12513, 12521, 12501, 12583, 12594, 12598, 12589, 12615, 12615, 12611, 12573, 12593, 12564], 'Sequence': [-1, -2, -3, 1, 2, 3, -1, -2, 1, -1, 1, 2, 3, -1, -2, -3] } df = pd.DataFrame(data) # 第一步:给每个连续序列段分组 # 观察数据可知,-1或1是一段序列的开头,用这个标记来切分组 df['group'] = (df['Sequence'].isin([-1, 1])).cumsum() # 第二步:定义组内计算逻辑的函数 def compute_group_result(group): # 把组内的Sequence和value做映射,方便快速查找 seq_to_value = group.set_index('Sequence')['value'] seq_order = group['Sequence'].tolist() # 处理以-1开头的负序列组 if seq_order[0] == -1: # 优先检查是否符合规则1:存在-2和-3 if -2 in seq_to_value and -3 in seq_to_value: return seq_to_value[-3] - seq_to_value[-2] # 再检查是否符合规则3:存在-2但无-3,且有1 elif -2 in seq_to_value and 1 in seq_to_value: return seq_to_value[-2] - seq_to_value[1] # 不符合规则的情况返回None,后续过滤掉 else: return None # 处理以1开头的正序列组 elif seq_order[0] == 1: # 检查是否符合规则2:存在2和3 if 2 in seq_to_value and 3 in seq_to_value: return seq_to_value[2] - seq_to_value[3] # 规则4的情况已被分组逻辑解决:-1会开启新组,不会和当前组混淆 else: return None # 第三步:对每个组应用计算,整理成目标格式 final_result = df.groupby('group').apply(compute_group_result)\ .dropna()\ .reset_index(drop=True)\ .to_frame('Calculation') print(final_result)
运行结果
完全匹配你期望的输出:
Calculation 0 -12 1 20 2 -4 3 4 4 -29
逻辑说明
- 分组逻辑:用
cumsum()把每个-1/1出现的位置作为新组起点,完美解决规则4的问题——只要出现-1或1就开启新组,不会和之前的序列段混淆,自然跳过不需要计算的情况。 - 组内计算:先判断组的类型(负/正序列开头),再按优先级检查规则,先处理规则1/2,再处理规则3,不符合的返回
None后过滤掉,保证结果只保留有效计算值。
这个写法清晰易维护,之后如果规则有调整,直接修改compute_group_result函数即可~
内容的提问来源于stack exchange,提问作者Show_man
相关产品推荐
相关产品推荐

