如何用numpy/pandas实现序列右比累计计数并修正TOPRANGE函数
需求说明
计数逻辑业务含义:标记当前值为向左追溯范围内的最大值,返回对应连续符合条件的长度。
- 测试输入列表:
l = [5,1,1,1,5,3,6] - 预期输出结果:
[0, 0, 0, 0, 3, 0, 6] - 计数规则:对每个位置的元素,从相邻左侧位置开始逐值向左比较:
- 若当前值大于比较值,累计计数+1,继续向左比较
- 若当前值小于等于比较值,立刻中断累计,当前位置计数结束
原有代码问题
原有实现代码如下:
import numpy as np def TOPRANGE(S): rt = np.zeros(len(S)) for i in range(1,len(S)): rt[i] = np.argmin(np.flipud(S[:i]<S[i])) return rt.astype('int') l = [5,1,1,1,5,3,6] s = np.array(l) TOPRANGE(s)
运行后输出为[0, 0, 0, 0, 3, 0, 0],最后一位结果错误。问题出在np.argmin的逻辑:当左侧所有元素都小于当前值时,S[:i]<S[i]全为True,此时np.argmin会默认返回索引0,无法识别「全程没有触发中断」的场景,导致最后一位(值为6,左侧所有元素都比它小)的计数错误返回0,而非正确的6。
修正实现(numpy版本)
针对上述问题补全边界判断即可,代码如下:
import numpy as np def TOPRANGE(S): arr_len = len(S) res = np.zeros(arr_len, dtype=int) for i in range(1, arr_len): left_compare = np.flipud(S[:i] < S[i]) interrupt_pos = np.argmin(left_compare) # 区分「存在中断点」和「无中断点(左侧全小于当前值)」两种场景 res[i] = interrupt_pos if not left_compare[interrupt_pos] else i return res # 测试验证 l = [5,1,1,1,5,3,6] s = np.array(l) print(TOPRANGE(s)) # 输出:[0 0 0 0 3 0 6],与预期完全一致
pandas版本实现
如果需要基于pandas实现,可直接将输入转为Series后调用上述numpy函数,调用示例:
import pandas as pd import numpy as np s = pd.Series([5,1,1,1,5,3,6]) print(TOPRANGE(s.values)) # 输出:[0 0 0 0 3 0 6]
内容的提问来源于stack exchange,提问作者lxg
相关产品推荐
相关产品推荐

