我有三个1D numpy数组:
t
)。t
(y
)中每次发生的测量列表。b
)。以下是一个例子:
t = np.array([0.33856697, 1.69615293, 1.70257872, 2.32510279, 2.37788203, 2.45102176, 2.87518307, 3.60941650, 3.78275907, 4.37970516, 4.56480259, 5.33306546, 6.00867792, 7.40217571, 7.46716989, 7.6791613 , 7.96938078, 8.41620336, 9.17116349, 10.87530965]) y = np.array([ 3.70209916, 6.31148802, 2.96578172, 3.90036915, 5.11728629, 2.85788050, 4.50077811, 4.05113322, 3.55551093, 7.58624384, 5.47249362, 5.00286872, 6.26664832, 7.08640263, 5.28350628, 7.71646500, 3.75513591, 5.72849991, 5.60717179, 3.99436659]) b = np.array([ 1.7, 3.9, 9.5])
b
的元素落在粗体和斜体元素t
之间,将其分成四个长度不等的长度为2,7,10,1的片段。
我想对y
的每个段应用一个操作来获取大小为b.size + 1
的数组。具体来说,我想知道更多是否超过每个段中y
的一半值超出或低于某个偏差。
我目前正在使用for循环和切片来应用我的测试:
bias = 5
categories = np.digitize(t, b)
result = np.empty(b.size + 1, dtype=np.bool_)
for i in range(result.size):
mask = (categories == i)
result[i] = (np.count_nonzero(y[mask] > bias) / np.count_nonzero(mask)) > 0.5
这似乎效率极低。不幸的是,np.where
在这种情况下没有多大帮助。有没有办法对我在这里描述的操作进行矢量化以避免Python for
循环?
顺便说一下,这是y
与t
,bias
以及由b
分隔的区域的图,以说明预期result
的原因是array([False, False, True, False], dtype=bool)
:
由
生成from matplotlib import pyplot as plt
from matplotlib.patches import Rectangle
plt.ion()
f, a = plt.subplots()
a.plot(t, y, label='y vs t')
a.hlines(5, *a.get_xlim(), label='bias')
plt.tight_layout()
a.set_xlim(0, 11)
c = np.concatenate([[0], b, [11]])
for i in range(len(c) - 1):
a.add_patch(Rectangle((c[i], 2.5), c[i+1] - c[i], 8 - 2.5, alpha=0.2, color=('red' if i % 2 else 'green'), zorder=-i-5))
a.legend()
答案 0 :(得分:2)
不应该产生相同的结果吗?
split_points = np.searchsorted(t, np.r_[t[0], b, t[-1]])
numerator = np.add.reduceat(y > bias, split_points[:-1])
denominator = np.diff(split_points)
result = (numerator / denominator) > 0.5
很少有人注意到:这种方法依赖于排序。那么相对于b的bin将都是整齐的块,所以我们不需要掩码来描述它们,而只需要将索引形式的端点描述为t。这是searchsorted
为我们找到的内容。
由于您的标准似乎不依赖于群组,因此我们可以一次性为所有y制作一个大面具。在布尔数组中计算非零值与求和相同,因为True将被强制转换为等等。在这种情况下的优点是我们可以使用add.reduceat
来获取数组,一个拆分列表点然后对分裂之间的块进行求和,这正是我们想要的。
为了规范化,我们需要计算每个bin中的总数,但由于这些bin是连续的,我们只需要使用split_points来区分该bin,这就是我们使用diff
的位置。