Есть ли способ понять кластеры нулей, а затем удалить его из массива NumPy? - PullRequest
1 голос
/ 19 июня 2019

Я хочу удалить нули из середины массива NumPy (но не все нули должны быть удалены)

Удаление нулей продемонстрировано в нескольких примерах в стеке потока, но мне все еще сложно написатьлогика для моей проблемы.

import numpy as np

a = np.array([255,255,255,255,255
,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
,255,255,255,255,255,255,255,255,255,255,255,255,255,0,255,255,255,255
,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,207,0,0
,159,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
,255,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0,0,0,0,88,239,255,255,255,255,255,255,255
,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,231,88])

У меня есть массив a, в котором есть несколько ненулевых значений и большой кластер нулей (вместе с некоторыми нулями в середине ненулевых значений).Я хочу удалить этот большой кластер нулей или найти индекс, где начинается этот большой кластер.Затем уменьшите массив до следующей формы:

a1 = [255,255,255,255,255
,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
,255,255,255,255,255,255,255,255,255,255,255,255,255,0,255,255,255,255
,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,207,0,0
,159,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
,255,64]

и

a2=[88,239,255,255,255,255,255,255,255
,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,231,88]

Обратите внимание, что в массиве a1 все еще есть несколько нулей.операция должна удалять нули только в том случае, если в ней есть определенное количество последовательных нулей (скажем, 10 нулей).Я могу сделать это с помощью циклов, повторяющихся в массиве, но если можно предложить более простой и быстрый подход, это было бы здорово.

Ответы [ 2 ]

0 голосов
/ 19 июня 2019

Вот еще один способ сделать это, используя в основном numpy, а не какие-либо массивы (за пределами списка понимания). Основная идея состоит в том, чтобы получить список [(value1, count1), (value2, count2)...] и затем выполнить поиск в этом списке для требуемого условия.

Есть пара вещей, которые можно улучшить, прежде всего, дважды проверив условия.

import numpy as np

a = np.array([255,255,255,255,255
,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
,255,255,255,255,255,255,255,255,255,255,255,255,255,0,255,255,255,255
,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,207,0,0
,159,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
,255,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0,0,0,0,0,0,0,88,239,255,255,255,255,255,255,255
,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,231,88])

def remove_consecutive(thearray, num, count):

    # Find the indices where there is a *change* in value
    adiff = np.diff(a)
    indices = np.hstack((np.array([0]), np.where(adiff)[0]+1))

    # Given the indices we can find the lengths of the lists by just doing a                                                                     
    # diff on the indices. Have to append a dummy so the last value is included.                                                                 
    lengths = np.diff(indices, append=indices[-1]+1)

    # Now construct a tuple of (value, length)
    the_list = list(zip(a[indices], lengths))

    # Find the places where we need to split based on the num/count requirement.                                                                 
    index_breaks = np.array([ii for ii, (lvalue, lcount) in enumerate(the_list) if lvalue == num and lcount > count])                            

    # Split the (value,length) list based on the index_breaks
    the_list_split = np.split(the_list, index_breaks)

    # Now expand back out.
    output_list = [ np.array([lvalue for lvalue, lcount in sublist for _ in range(lcount) if not( lvalue == num and lcount > count)])            
                    for sublist in the_list_split]

    return np.array(output_list).flatten()

a1, a2 = remove_consecutive(a, 0, 10)

print(a1)
print(a2)

Вывод:

[255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
   0 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
 255 255 207   0   0 159 255 255 255 255 255 255 255 255 255 255 255 255
 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
 255 255 255 255 255 255  64]
[ 88 239 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
 255 255 255 255 255 255 231  88]
0 голосов
/ 19 июня 2019

Без импорта, используя один цикл:

def remove_clusters(my_array, cluster_value, consecutive_max=10):
    my_result = [[]]
    cluster_list = []
    for e in my_array:
        if e == cluster_value:
            cluster_list.append(e)
        else:
            if len(cluster_list) <= consecutive_max:
                my_result[-1].extend(cluster_list)
            else:
                my_result.append([])
            cluster_list = []
            my_result[-1].append(e)
    return my_result

Я получил это, используя itertools.groupby, что немного упрощает код:

def remove_clusters(my_array, cluster_value=0, max_consecutive=10):
    from itertools import groupby
    my_result = [[]]
    for k,g in groupby(my_array):
        g = list(g)
        if k != cluster_value or len(g) <= max_consecutive:
            my_result[-1].extend(g)
        else:
            my_result.append([])
    return my_result

Тогда вы можете сделать:

a1, a2 = remove_clusters(a)

Наконец, очень уродливый пользователь, использующий functools.reduce

from itertools import groupby
from functools import reduce
a1, a2 = reduce(lambda x,y: x + [[]] if not y[0] and len(y)>10 
                       else x[:-1] + [x[-1]+y], 
                map(lambda x: list(x[1]), groupby(a)), 
                [[]])

Я бы с удовольствием объяснил это, но уже не понимаю.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...