Простой способ перебора - просто использовать numpy.where
.
Например, если вы просто хотите ограничить поле :
import numpy as np
x = np.array([[1,1,2,2],
[1,1,2,2],
[3,3,4,4],
[3,3,4,4]])
for val in np.unique(x):
rows, cols = np.where(x == val)
rowstart, rowstop = np.min(rows), np.max(rows)
colstart, colstop = np.min(cols), np.max(cols)
print val, (rowstart, colstart), (rowstop, colstop)
Это будет работать и для примера с нулями.
Если массив большой, и у вас уже есть scipy
, вы можете вместо этого использовать scipy.ndimage.find_objects
, как предложил @unutbu.
В конкретном случае вашего примера, где ваши уникальные значения являются последовательными целыми числами, вы можете напрямую использовать find_objects
. Он ожидает массив, в котором каждое последовательное целое число, отличное от 0, представляет объект, которому необходимо вернуть ограничивающий прямоугольник. (0 игнорируется, именно так, как вы хотите.) Однако, как правило, вам необходимо выполнить предварительную обработку для преобразования произвольных уникальных значений в последовательные целые числа.
find_objects
возвращает список кортежей из slice
объектов. Честно говоря, это, вероятно, именно то, что вы хотите, если вам нужна коробка подарка. Однако распечатка индикации запуска и остановки будет выглядеть немного более беспорядочно.
import numpy as np
import scipy.ndimage as ndimage
x = np.array([[1, 0, 1, 2, 2],
[1, 0, 1, 2, 2],
[3, 0, 3, 4, 4],
[3, 0, 3, 4, 4]])
for i, item in enumerate(ndimage.find_objects(x), start=1):
print i, item
Это будет выглядеть немного иначе, чем вы могли бы ожидать. Это slice
объекты, поэтому значение «max» всегда будет на единицу больше, чем «max» в предыдущем примере. Это сделано для того, чтобы вы могли просто нарезать данный кортеж, чтобы получить данные.
1026 * Е.Г. *
for i, item in enumerate(ndimage.find_objects(x), start=1):
print i, ':'
print x[item], '\n'
Если вы действительно хотите запускать и останавливать, просто сделайте что-то вроде этого:
for i, (rowslice, colslice) in enumerate(ndimage.find_objects(x), start=1):
print i,
print (rowslice.start, rowslice.stop - 1),
print (colslice.start, colslice.stop - 1)
Если ваши уникальные значения не являются последовательными целыми числами, вам необходимо выполнить небольшую предварительную обработку, как я уже упоминал ранее. Вы можете сделать что-то вроде этого:
import numpy as np
import scipy.ndimage as ndimage
x = np.array([[1.1, 0.0, 1.1, 0.9, 0.9],
[1.1, 0.0, 1.1, 0.9, 0.9],
[3.3, 0.0, 3.3, 4.4, 4.4],
[3.3, 0.0, 3.3, 4.4, 4.4]])
ignored_val = 0.0
labels = np.zeros(data.shape, dtype=np.int)
i = 1
for val in np.unique(x):
if val != ignored_val:
labels[x == val] = i
i += 1
# Now we can use the "labels" array as input to find_objects
for i, item in enumerate(ndimage.find_objects(labels), start=1):
print i, ':'
print x[item], '\n'