Количество элементов массивов 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. Я предполагаю, что вы не пробовали это или упомянули об этом!

Конечно, возможно, что вы могли бы использовать отсортированную природу, чтобы найти более быстрое решение, но я бы начал со сравнения времени.

Другие вопросы по тегам