如何对自定义Event对象的numpy数组高效筛选并修改alive属性?
高效筛选numpy数组中Event对象并修改属性
背景定义
已定义Event类:
class Event(object): def __init__(self, time): self.time = time self.alive = True def __repr__(self): return f"t = {self.time:.2E}"
现有按time排序的numpy数组timestamps,存储Event对象:
timestamps >>> array([t = 5.00E-11, t = 1.51E-08, t = 3.15E-08, t = 4.69E-08], dtype=object)
需求
筛选出time处于指定区间(target, target + t_dead)内的数组元素,将其alive属性设为False。原嵌套for循环速度过慢,希望用类似布尔掩码的高效写法实现。
可行实现方式
方法1:布尔掩码筛选
先提取所有Event对象的time值为数值数组,再生成布尔掩码筛选目标元素:
import numpy as np # 提取所有time值到numpy数值数组 times = np.array([event.time for event in timestamps]) # 定义目标区间 target = timestamps[i].time t_dead = 1e-8 # 替换为实际需求值 # 生成布尔掩码 mask = (times > target) & (times < target + t_dead) # 修改筛选出的元素的alive属性 for event in timestamps[mask]: event.alive = False
方法2:利用数组有序性优化(二分查找)
由于timestamps已按time排序,可使用np.searchsorted快速定位区间边界,大幅减少遍历范围:
import numpy as np times = np.array([event.time for event in timestamps]) target = timestamps[i].time t_dead = 1e-8 # 二分查找区间左右边界 left_idx = np.searchsorted(times, target, side='right') right_idx = np.searchsorted(times, target + t_dead, side='left') # 修改区间内元素的alive属性 for event in timestamps[left_idx:right_idx]: event.alive = False
这种方法时间复杂度更低(O(logN)定位边界 + O(K)修改元素,K为区间内元素数量),适合处理大规模数组。
方法3:用np.vectorize简化属性提取
如果觉得列表推导提取time不够简洁,可使用np.vectorize包装属性获取逻辑:
import numpy as np get_time = np.vectorize(lambda event: event.time) times = get_time(timestamps) target = timestamps[i].time t_dead = 1e-8 mask = (times > target) & (times < target + t_dead) for event in timestamps[mask]: event.alive = False
注意:np.vectorize本质是对循环的封装,性能和列表推导接近,主要作用是简化写法。
内容的提问来源于stack exchange,提问作者Sala
相关产品推荐
相关产品推荐

