Число логических массивов numpy 2d подряд истинные размеры

Я заинтересован в том, чтобы узнать отдельные размеры "истинных" патчей в логическом массиве. Например, в логической матрице:

[[1, 0, 0, 0],
 [0, 1, 1, 0],
 [0, 1, 0, 0],
 [0, 1, 0, 0]]

Выход будет:

[[1, 0, 0, 0],
 [0, 4, 4, 0],
 [0, 4, 0, 0],
 [0, 4, 0, 0]]

Я знаю, что могу сделать это рекурсивно, но у меня также сложилось впечатление, что операции с массивами python в больших масштабах являются дорогостоящими, и есть ли доступная библиотечная функция для этого?

1 ответ

Решение

Вот быстрое и простое полное решение:

import numpy as np
import scipy.ndimage.measurements as mnts

A = np.array([
    [1, 0, 0, 0],
    [0, 1, 1, 0],
    [0, 1, 0, 0],
    [0, 1, 0, 0]
])

# labeled is a version of A with labeled clusters:
#
# [[1 0 0 0]
#  [0 2 2 0]
#  [0 2 0 0]
#  [0 2 0 0]]
#
# clusters holds the number of different clusters: 2
labeled, clusters = mnts.label(A)

# sizes is an array of cluster sizes: [0, 1, 4]
sizes = mnts.sum(A, labeled, index=range(clusters + 1))

# mnts.sum always outputs a float array, so we'll convert sizes to int
sizes = sizes.astype(int)

# get an array with the same shape as labeled and the 
# appropriate values from sizes by indexing one array 
# with the other. See the `numpy` indexing docs for details
labeledBySize = sizes[labeled]

print(labeledBySize)

выход:

[[1 0 0 0]
 [0 4 4 0]
 [0 4 0 0]
 [0 4 0 0]]

Самая хитрая строчка выше - это "фантазия" numpy индексация:

labeledBySize = sizes[labeled]

в котором один массив используется для индексации другого. Увидеть numpy индексирование документов (раздел "Индексные массивы"), чтобы узнать, почему это работает.

Я также написал версию приведенного выше кода в виде единой компактной функции, которую вы можете попробовать самостоятельно в Интернете. Он включает в себя тестовый набор на основе случайного массива.

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