Предположим, у меня есть следующий массив 4 на 3 на 3,
array([[[-2, -2, -2],
[-2, -2, -2],
[-2, -2, -2]],
[[-2, -2, -2],
[-2, -2, -2],
[-2, -2, -2]],
[[-2, -2, 71],
[-1, -1, -1],
[71, -1, 52]],
[[-2, -2, -2],
[-2, -2, -2],
[-2, -2, -2]]])
Я хотел бы отфильтровать такой массив по следующему стандарту:
Рассматривайте каждый массив 3 на 3 как блок. Если все элементы в этом блоке равны -2, мы должны вырезать весь блок, чтобы целевой массив выглядел так (1 на 3 на 3):
array([[[-2, -2, 71],
[-1, -1, -1],
[71, -1, 52]]])
Я мог только придумать решение грубой силы с явным условием if
и циклом for
, но оно не работает. Может ли кто-нибудь поделиться лучшим методом?
Вы можете воссоздать исходный массив с помощью следующих команд
array = np.array([[-2,-2,-2,-2,-2,-2,-2,-2,-2],
[-2,-2,-2,-2,-2,-2,-2,-2,-2],
[-2,-2,71,-1,-1,-1,71,-1,52],
[-2,-2,-2,-2,-2,-2,-2,-2,-2]])
newarr = array.reshape(4,3,3)
Вы можете сделать это, он использует функцию массива фильтров и функцию all()
в NumPy:
filterarr = []
for arr in newarr:
if np.all(arr==-2):
filterarr.append(False)
else:
filterarr.append(True)
newarr = newarr[filterarr]
print(newarr)
Другие ответы хороши, если вы ожидаете, что ваши массивы вдоль оси 0 всегда будут иметь определенное значение, например -2 или 872385 и т. д.
Если вам нужно что-то более общее, где вы хотите отфильтровать любые массивы, содержащие одно значение, вы можете фильтровать массивы по рангу.
Поскольку любая матрица с одним значением будет иметь ранг 1, вы можете отфильтровать по rank != 1
:
In [2]: x[np.linalg.matrix_rank(x) != 1]
Out[2]:
array([[[-2, -2, 71],
[-1, -1, -1],
[71, -1, 52]]])
Это будет работать для любой матрицы вдоль оси 0, которая заполнена одними и теми же значениями. Другой пример:
In [4]: x
Out[4]:
array([[[ 5, 5, 5],
[ 5, 5, 5],
[ 5, 5, 5]],
[[-2, -2, -2],
[-2, -2, -2],
[-2, -2, -2]],
[[-2, -2, 71],
[-1, -1, -1],
[71, -1, 52]],
[[99, 99, 99],
[99, 99, 99],
[99, 99, 99]]])
In [5]: x[np.linalg.matrix_rank(x) != 1]
Out[5]:
array([[[-2, -2, 71],
[-1, -1, -1],
[71, -1, 52]]])
Вы можете использовать np.where
:
data[np.where(np.any(data != -2, axis=-1))]
С данным массивом в виде data
результат будет следующим:
[[-2 -2 71]
[-1 -1 -1]
[71 -1 52]]
Можно просто выбрать для отрицания, где все массивы по 2-й и 3-й осям равны -2
:
>>> arr
array([[[-2, -2, -2],
[-2, -2, -2],
[-2, -2, -2]],
[[-2, -2, -2],
[-2, -2, -2],
[-2, -2, -2]],
[[-2, -2, 71],
[-1, -1, -1],
[71, -1, 52]],
[[-2, -2, -2],
[-2, -2, -2],
[-2, -2, -2]]])
>>> ~(arr == -2).all(axis=(1,2))
array([False, False, True, False])
И используйте логическое индексирование на первой оси:
>>> arr[~(arr == -2).all(axis=(1,2)), ...]
array([[[-2, -2, 71],
[-1, -1, -1],
[71, -1, 52]]])
Это решение также будет фильтровать сингулярные матрицы.