Количество элементов массивов numpy внутри конкретных бинов
У меня есть ансамбль отсортированных (одномерных) массивов неравной длины (скажем, M0
, M1
а также M2
). Я хочу выяснить, сколько элементов каждого из этих массивов находится в определенных диапазонах номеров (где диапазоны номеров указаны соседними элементами из другого отсортированного массива, скажем, zbin
). Я хочу знать, какой самый быстрый способ достичь этого.
Здесь я приведу небольшой пример задачи, которую я хочу выполнить (а также метод, которым я сейчас следую для достижения желаемой функциональности):
""" Function to do search query """
def search(numrange, lst):
arr = np.zeros(len(lst))
for i in range(len(lst)):
probe = lst[i]
count = 0
for j in range(len(probe)):
if (probe[j]>numrange[1]): break
if (probe[j]>=numrange[0]) and (probe[j]<=numrange[1]): count = count + 1
arr[i] = count
return arr
""" Some example of sorted one-dimensional arrays of unequal lengths """
M0 = np.array([5.1, 5.4, 6.4, 6.8, 7.9])
M1 = np.array([5.2, 5.7, 8.8, 8.9, 9.1, 9.2])
M2 = np.array([6.1, 6.2, 6.5, 7.2])
""" Implementation and output """
lst = [M0, M1, M2]
zbin = np.array([5.0, 5.5, 6.0, 6.5])
zarr = np.zeros( (len(zbin)-1, len(lst)) )
for i in range(len(zbin)-1):
numrange = [zbin[i], zbin[i+1]]
zarr[i,:] = search(numrange, lst)
print zarr
Выход:
[[ 2. 1. 0.]
[ 0. 1. 0.]
[ 1. 0. 3.]]
Здесь, окончательный вывод zarr
дает мне количество элементов каждого из массивов (M0
, M1
а также M2
внутри каждого из бункеров возможно из zbin
(а именно [5.0, 5.5]
, [5.5, 6.0]
а также [6.0, 6.5]
.) Например, рассмотрим мусорное ведро [5.0, 5.5]
, Массив M0
имеет 2 элемента внутри этого бункера (5.1
а также 5.4
), M1
имеет 1 элемент (5.2
) а также M2
имеет 0 элементов в этой корзине. Это дает первый ряд zarr
т.е. [2,1,0]
, Можно получить другие ряды zarr
аналогичным образом.
В моей реальной задаче я буду иметь дело с zbin
длины намного больше, чем то, что я дал в этом примере, а также больше и много других массивов, таких как M0
, M1
, ...
Mn
, Все M
с и массив zbin
будет отсортирован всегда. Мне интересно, если функция, которую я разработал (search()
), и метод, которым я следую, является наиболее оптимальным и быстрым способом достижения желаемой функциональности. Я буду очень признателен за любую помощь.
2 ответа
Мы могли бы использовать отсортированную природу и, следовательно, использовать np.searchsorted
для этой задачи вот так -
out = np.empty((len(zbin)-1, len(lst)),dtype=int)
for i,l in enumerate(lst):
left_idx = np.searchsorted(l, zbin[:-1], 'left')
right_idx = np.searchsorted(l, zbin[1:], 'right')
out[:,i] = right_idx - left_idx
Я предполагаю, что было бы трудно превзойти производительность, просто циклически обрабатывая каждый массив и вызывая numpy.histogram. Я предполагаю, что вы не пробовали это или упомянули об этом!
Конечно, возможно, что вы могли бы использовать отсортированную природу, чтобы найти более быстрое решение, но я бы начал со сравнения времени.