@memecs的解决方案是正确的,+1。然而,如果input_1
中的值非常大,即它们不是数组的索引,而是秒或其他可以取很大值的整数数据,那么这种方法将非常缓慢并且占用大量内存。
在这种情况下,您可以通过np.bincount(input_1[input_2]).size
来确定具有input_2
中True
值的最大整数在input_1
数组中出现的次数。
使用unique
和bincount
会更快。我们使用第一个函数提取input_1
中唯一元素的索引,然后使用bincount
计算该同一数组中这些索引出现的次数,并根据数组input_2
的值(True
或False
)将它们加权为1
或0
:
unq, idx = np.unique(input_1, return_inverse=True)
freqs_idx = np.bincount(idx, weights=input_2)
frequencies = freqs_idx[idx]
print(frequencies)
这个解决方案非常快,并且对内存的影响最小。感谢 @Jaime,可以看到他下面的评论。下面我将报告我的原始答案,以不同的方式使用 unique
。
另一种可能性
使用 unique
可能更快:
import numpy as np
input_1 = np.array([3, 6, 6, 3, 6, 4])
input_2 = np.array([False, True, True, False, False, True])
non_zero_hits, counts = np.unique(input_1[input_2], return_counts=True)
all_hits, idx = np.unique(input_1, return_inverse=True)
frequencies = np.zeros_like(all_hits)
idx_non_zero_hits_in_all_hits = np.where(non_zero_hits[:, np.newaxis] - all_hits == 0)[1]
frequencies[idx_non_zero_hits_in_all_hits] = counts
print(frequencies[idx])
这种方法的缺点在于,如果 input_1
中唯一元素的数量很多且值为 True
的元素也很多,则会需要大量的内存,因为需要创建并传递给 where
的是一个二维数组。为了减少内存占用,您可以使用 for 循环来替代算法的第二步:
for j, val in enumerate(non_zero_hits):
index = np.where(val == all_hits)[0]
frequencies[index] = counts[j]
print(frequencies[idx])
这种第二种解决方案的内存占用很小,但需要使用 for
循环。哪种解决方案最优取决于您的典型数据输入大小和值。
np.bincount
的weights
参数:unq, idx = np.unique(array_1, return_inverse=True); freqs = np.bincount(idx, weights=array2)[idx]
将为您提供快速、紧凑且内存高效的实现。 - Jaime