Как использовать .delete () для удаления указанного c массива в numpy при его повторении? - PullRequest
3 голосов
/ 03 апреля 2020

Во-первых, я прочитал о этой проблеме

У меня есть np.array (с картинки)

[[255 255 255 ... 255 255 255]
 [255 255 0 ... 255 255 255]
 [255 255 255 ... 255 255 255]
 ...
 [255 255 0 ... 0 255 255]
 [255 255 0 ... 255 255 255]
 [255 255 255 ... 255 255 255]]

Я хочу удалить строку, которая сумма 0 меньше указанного значения c. Мой код:

import numpy
from collections import Counter

for i in range(pixelarray.shape[0]):
    # Counter(pixelarray[i])[0] represent the amount of 0 in one row.
    if Counter(pixelarray[i])[0] < 2: # check the amount of 0,if it is smaller than 2,delete it.
        pixelarray = np.delete(pixelarray,i,axis=0) # delete the row
print(pixelarray)

Но возникла ошибка:

Traceback (most recent call last):
  File "E:/work/Compile/python/OCR/PictureHandling.py", line 23, in <module>
    if Counter(pixelarray[i])[0] <= 1:
IndexError: index 183 is out of bounds for axis 0 with size 183

Что мне делать?

Ответы [ 3 ]

3 голосов
/ 03 апреля 2020
if Counter(pixelarray[i])[0] <= 1:
IndexError: index 183 is out of bounds for axis 0 with size 183

В этом выражении pixelarray[i] - единственная часть, которая может вызвать эту ошибку. Это ошибка numpy, говорящая нам, что i слишком велико для текущей формы pixelarray.

pixelarray - это двумерный массив. i считается вверх по направлению к pixelarray.shape[0] (исходная форма). Но вы удаляете строки из pixelarray в цикле; это уменьшается. Так что в какой-то момент счетчик выходит за пределы текущего размера массива.

Это может произойти в базе Python, если вы удалите элементы из списка в al oop.

In [456]: alist = [1,2,3,4]                                                                    
In [457]: for i in range(len(alist)): 
     ...:     print(i, alist) 
     ...:     del alist[i] 
     ...:                                                                                      
0 [1, 2, 3, 4]
1 [2, 3, 4]
2 [2, 4]
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-457-5e5f105666aa> in <module>
      1 for i in range(len(alist)):
      2     print(i, alist)
----> 3     del alist[i]
      4 

IndexError: list assignment index out of range

Посмотрите, как сокращается список при увеличении i. К i=2 список уменьшен до 2 пунктов, поэтому alist[2] больше не действителен. Обратите внимание, как он также опустил «3», а не «1». Если мое намерение было удалить последовательные значения из списка, это не работает.

С помощью списков способ обойти проблему такого рода - удалить с конца

In [463]: for i in range(len(alist),0,-1): 
     ...:     print(i, alist) 
     ...:     del alist[i-1] 
     ...:      
     ...:                                                                                      
4 [1, 2, 3, 4]
3 [1, 2, 3]
2 [1, 2]
1 [1]
In [464]: alist                                                                                
Out[464]: []

В вашем случае np.delete создает новый массив при каждом вызове. Для массивов это довольно неэффективно. Таким образом, проблема индексации или нет, мы не рекомендуем повторное удаление, как это. Однако вы можете собрать все нужные индексы «удаления» в списке (добавление в список эффективно) и выполнить удаление в конце. np.delete берет список индексов.

3 голосов
/ 03 апреля 2020

np.delete, вероятно, не лучший выбор для этой проблемы. Это можно решить, просто замаскировав строки, которые не соответствуют требуемым критериям. Для этого вы начинаете с подсчета количества нулей в строке:

zeros_per_row = (pixelarray == 0).sum(1)

Сначала сравнивается каждое значение в pixelarray с нулем, а затем суммируется (подсчитывается количество True значений) его столбцов. (ось 1), поэтому вы получите количество нулей в каждом ряду. Затем вы можете просто сделать:

rows_with_min_zeros = pixelarray[zeros_per_row >= MIN_ZEROS]

Здесь zeros_per_row >= MIN_ZEROS создает логический массив, где каждое значение, большее или равное MIN_ZEROS, равно True. Используя индексирование логического массива , это можно использовать для исключения строк, где оно равно False, то есть строк, в которых число нулей меньше MIN_ZEROS.

0 голосов
/ 03 апреля 2020

просто используйте копию pixelarray при итерации. Попробуйте это:

import numpy
from collections import Counter
from copy import copy

pixelarray2 = copy(pixelarray)
for i in range(pixelarray2.shape[0]):
    # Counter(pixelarray[i])[0] represent the amount of 0 in one row.
    if Counter(pixelarray2[i])[0] < 2: # check the amount of 0,if it is smaller than 2,delete it.
        pixelarray = np.delete(pixelarray,i,axis=0) # delete the row
print(pixelarray)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...