Как удалить элементы массива, если соответствующие элементы другого массива имеют нулевые значения в Python?

#python #numpy #numpy-ndarray

Вопрос:

У меня есть HSI массив с формой (250, 1376, 176). Он представляет собой гиперспектральное изображение с 176 каналами. У меня также есть изображение основной истины GT с формой (250, 1376). Я хочу удалить элементы GT массива, которые имеют нулевые значения. Поэтому я воспользовался этим:

 GT_nonzero = GT[GT!= 0]
 

Но тогда у меня есть вектор. Я хотел бы создать GT_nonzero 2D-массив. Есть ли способ создать 2D-массив из 2D-массива с вычитанием элементов с нулевым значением?

Затем я хочу удалить пиксели HSI массива (а именно элементы второй и третьей оси массива), которые соответствуют элементам GT массива, имеющим нулевые значения. Я пытался с numpy.argwhere() помощью функции найти индексы ненулевых элементов GT массива, но я застрял и не могу найти решение. Кто-нибудь может предложить решение?

Комментарии:

1. Как распределяются эти 0 элементов? Какова была бы форма желаемого 2d GT_nonzero ? Потренируйтесь с небольшим GT , чтобы вы получили четкое(э-э) представление о том, что происходит.

2. почему GT_nonzero = GT[GT!= 0] приводит к 1d массиву (вектору) ?

3. @pippo1980, индексирование с помощью логического массива возвращает массив 1d; это четко указано в numpy документах по индексированию.

4. Представьте себе что-то вроде x = [[0, 1], [2, 3]] . Как бы вы ожидали, что это будет выглядеть, когда вы удалите нули?

5. Пока вы размышляете над этим, я предлагаю изучить массивы в масках.

Ответ №1:

Сначала нам нужно уточнить, чего вы хотите, когда говорите, что хотите удалить элементы со значением 0. В 1D-массивах это просто, просто отбросьте этот элемент, но в 2D-массиве что вы делаете с этим пустым пространством? Возможно, остальные значения одной и той же строки и столбца не являются нулями, поэтому этот элемент все равно будет занимать место в этом 2D-массиве. Поэтому я предполагаю, что вы хотите удалить полные строки или столбцы, в которых все элементы равны 0. Это единственный способ, которым вы могли бы избавиться от элементов.

Поэтому для достижения этой цели давайте воспользуемся простым примером, 2D-массивом, таким как этот:

 GT = np.zeros((3,4))
GT[2,2] = 1
GT[2,0] = 1
GT[0,3] = 1
 

который имеет такую форму:

 [[0. 0. 0. 0.]
 [0. 0. 0. 1.]
 [1. 0. 1. 0.]]
 

таким образом, очень наглядно видно, что есть строка и столбец, в которых всего 0. Теперь мы можем проверить, в каких столбцах и строках есть только 0, как это:

 #check if any row only has 0s
rows_to_delete = []
for i in range(np.shape(GT)[0]):
    if not np.any(GT[i]):
        rows_to_delete.append(i)

#check if any column only has 0s
columns_to_delete = []
for i in range(np.shape(GT)[1]):
    if not np.any(GT[:,i]):
        columns_to_delete.append(i)
 

Итак, теперь, когда у нас есть соответствующие строки и столбцы, нам просто нужно удалить их, что мы и делаем с помощью np.delete метода (третий параметр, указывающий ось, 0 для строк и 1 для столбцов; и второй параметр, указывающий, какая конкретная строка или столбец).:

 GT_del = np.delete(np.delete(GT, rows_to_delete, 0), columns_to_delete, 1)
 

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

 GT_del_rows = np.delete(GT, rows_to_delete, 0)
GT_del_all = np.delete(GT_del_rows, columns_to_delete, 1)
 

Таким образом, таким образом, вы избавите свой 2D-массив GT от пустых строк и столбцов (конечный результат показан ниже). Отсюда я бы предложил создать 2D-массив HSI из этого, так как в противном случае вам придется выполнять одну и ту же операцию дважды.

 [[0. 0. 1.]
 [1. 1. 0.]]