寻求基于Numpy的遇0重置向量化累积求和实现方案
我懂你想要的是完全基于NumPy的向量化方案来实现「遇到0就重置的累积求和」——先看你的例子:输入ar = np.array([0,1,0,1,1,0,1,0]),期望输出np.array([0,1,0,1,2,0,1,0])。你现有的两种方法要么依赖pandas分组,要么需要循环拆分数组,确实不够纯粹的向量化。这里给你两个高效的纯NumPy向量化实现:
方法1:累积和减去最近重置点(最优方案)
这个思路的核心是用全局累积和,减去每个位置最近一次0对应的累积值,就能得到从最近的0开始的局部累积和:
import numpy as np ar = np.array([0,1,0,1,1,0,1,0]) # 计算全局累积和 cumsum_total = np.cumsum(ar) # 找到所有0的位置,加上开头的0作为初始重置点 zero_positions = np.concatenate([[0], np.where(ar == 0)[0]]) # 提取每个重置点对应的全局累积和 reset_values = cumsum_total[zero_positions] # 给每个元素分配分组ID(到当前位置为止出现的0的次数) group_ids = np.cumsum(ar == 0) # 用全局累积和减去对应分组的重置值,得到结果 result = cumsum_total - reset_values[group_ids] print(result) # 输出: [0 1 0 1 2 0 1 0]
这个方案完全用NumPy内置的向量化函数实现,没有任何循环或分组操作,处理大规模数组时效率拉满。
方法2:自定义累积操作
如果你更倾向于直观的逻辑,可以用np.frompyfunc把自定义的重置累积逻辑转为通用函数,再做累积计算:
import numpy as np def reset_cumsum(arr): # 自定义累积规则:遇到0就重置,否则累加前值 def accumulate_rule(prev_sum, current_val): return current_val if current_val == 0 else prev_sum + current_val # 把Python函数转为NumPy可处理的ufunc,再执行累积 ufunc = np.frompyfunc(accumulate_rule, 2, 1) return ufunc.accumulate(arr, dtype=object).astype(np.int64) ar = np.array([0,1,0,1,1,0,1,0]) print(reset_cumsum(ar)) # 输出: [0 1 0 1 2 0 1 0]
这个方法没有显式循环,依赖NumPy的累积机制,也算纯向量化实现,逻辑更贴近手动计算的思路。
对比你现有的方法
你提到的两种方案虽然可行,但都不算完全向量化:
- Pandas分组法:
import pandas as pd s = pd.Series(ar) data = s.groupby(s.eq(0).cumsum()).cumsum().tolist()
代码简洁,但底层依赖分组遍历,本质是隐式循环,且需要引入pandas库。
- np.split拆分法:
你没写完的代码大概是这种逻辑:
def intervaled_cumsum(ar): zero_indices = np.where(ar == 0)[0] splits = np.split(ar, zero_indices) result = [] for split in splits: result.extend(np.cumsum(split)) return np.array(result)
需要显式循环处理每个拆分后的子数组,当数组规模很大时,循环会成为性能瓶颈。
内容的提问来源于stack exchange,提问作者user9653473
相关产品推荐
相关产品推荐

