как заполнить начало и конец уникальной записи одним и тем же значением в массиве numpy? - PullRequest
0 голосов
/ 12 октября 2011

у меня есть 1D-массив. Давайте посмотрим на следующий пример

a = [255,1,255,255,1,255,255,255,2,2,255,255,255,2,2,3,255,255,255,3]

В приведенном выше массиве рассматриваются уникальные записи, кроме значения 255. Мы хотим заполнить значения между каждой уникальной записью.

результат будет выглядеть как

[255,1,1,1,1,255,255,255,2,2,2,2,2,2,2,3,3,3,3,3]    

можно очень легко сделать. В поисках питонского способа сделать это.

Большое спасибо

Ответы [ 4 ]

1 голос
/ 13 октября 2011

понятия не имею, что значит быть здесь питоническим, но только мои два цента,

import numpy as np    

a = np.array([255,1,255,255,1,255,255,255,2,2,255,255,255,2,2,3,255,255,255,3])

# find the locations of the unique numbers
b = np.where(a != 255)[0]
# find out what the unique numbers are
u = a[b]

for i,v in zip(b, u):
    try:
        if (v == vlast): # found a sandwich
            if (i != ilast+1): # make sure it has something in between 
                a[ilast+1: i] = v
        else: # make current unique value as the beginning of next sandwich
            vlast, ilast = v, i
    except NameError:
        # initialize the first match
        vlast, ilast = v, i

print(a)

дает правильный ответ:

[255   1   1   1   1 255 255 255   2   2   2   2   2   2   2   3   3   3   3   3]
1 голос
/ 13 октября 2011

Я использовал groupby функцию из itertools модуля.

Также я использовал window функцию от здесь .

from __future__ import print_function
from  itertools import tee, izip, groupby

a = [255,1,255,255,1,255,255,255,2,2,255,255,255,2,2,3,255,255,255,3]

def groupby2(iterable):
    '''Used to convert to the second iterable element of "groupby" result to list'''
    for i in groupby(iterable):
        yield (i[0],list(i[1]))


def window(iterable,n):
    els = tee(iterable,n)
    for i,el in enumerate(els):
        for _ in range(i):
            next(el, None)
    return izip(*els)

def compress(iterable):
    it = window(groupby2(iterable),3)
    #Creates the iterator which yield the elements in the following manner: (255, [255]), (1, [1]), (255, [255, 255])

    for ge in it:
        flag = False #Reset the flag
        print('\nWindow: {}'.format(ge))

        for value in ge[0][1]: #Yield all the values of the first element of the window
                print('A: {}'.format(value))
                yield value

        if ge[1][0]==255 and ge[0][0]==ge[2][0]: #The central element of the window has to be replaced
            flag = True #Flag for correct last window processing        

            for _ in ge[1][1]: #Replacing the central element of the window
                print('B: {}'.format(ge[0][0]))
                yield ge[0][0]

            next(it,None) #Skip 1 element of the 'it' (which will be advanced by 1 element by for-loop, giving 2 net advances).   

    #Processing the last 2 elements of the last window.
    if flag==False: #The central element of the last window hasn't been processed. Proccessing.
        for value in ge[1][1]:
            print('C: {}'.format(value))
            yield value
    for value in ge[2][1]: #The last element of the window.
        print('D: {}'.format(value))
        yield value


print('\nInput: {}'.format(a))
output = list(compress((a)))
print('Proram output: {}'.format(output))
print('Goal output  : {}'.format([255,1,1,1,1,255,255,255,2,2,2,2,2,2,2,3,3,3,3,3]))

Код с сообщениями отладки. Я проживу их здесь, так как они облегчают понимание того, как это работает. Просто удалите их, если они вам не нужны.

Вывод:

Input: [255, 1, 255, 255, 1, 255, 255, 255, 2, 2, 255, 255, 255, 2, 2, 3, 255, 255, 255, 3]

Window: ((255, [255]), (1, [1]), (255, [255, 255]))
A: 255

Window: ((1, [1]), (255, [255, 255]), (1, [1]))
A: 1
B: 1
B: 1

Window: ((1, [1]), (255, [255, 255, 255]), (2, [2, 2]))
A: 1

Window: ((255, [255, 255, 255]), (2, [2, 2]), (255, [255, 255, 255]))
A: 255
A: 255
A: 255

Window: ((2, [2, 2]), (255, [255, 255, 255]), (2, [2, 2]))
A: 2
A: 2
B: 2
B: 2
B: 2

Window: ((2, [2, 2]), (3, [3]), (255, [255, 255, 255]))
A: 2
A: 2

Window: ((3, [3]), (255, [255, 255, 255]), (3, [3]))
A: 3
B: 3
B: 3
B: 3
D: 3
Proram output: [255, 1, 1, 1, 1, 255, 255, 255, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3]
Goal output  : [255, 1, 1, 1, 1, 255, 255, 255, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3]

Обновление Вот пересмотренная версия:

from __future__ import print_function
from  itertools import tee, izip, groupby

def groupby2(iterable):
    for i in groupby(iterable):
        yield (i[0],len(tuple(i[1])))


def window(iterable,n):
    els = tee(iterable,n)
    for i,el in enumerate(els):
        for _ in range(i):
            next(el, None)
    return izip(*els)


def subs(iterable):
    it = window(groupby2(iterable),3)
    for left, middle, right in it:
        yield [left[0]]*left[1]
        if middle[0]==255 and left[0]==right[0]:
            yield [left[0]]*middle[1]
            next(it,None)
    if not(middle[0]==255 and left[0]==right[0]):
        yield [middle[0]]*middle[1]
    yield [right[0]]*right[1]


def chained(iterable):
    for L in subs(iterable):
        for el in L:
            yield el


a = [255,1,255,255,1,255,255,255,2,2,255,255,255,2,2,3,255,255,255,3]        
print('\nInput: {}'.format(a))
output = list(chained((a)))
print('Proram output: {}'.format(output))
print('Goal output  : {}'.format([255,1,1,1,1,255,255,255,2,2,2,2,2,2,2,3,3,3,3,3]))
0 голосов
/ 15 октября 2011

Другое решение состоит в использовании оконной функции с 2 элементами и ifilterfalse в списке перечисляемых значений.

from __future__ import print_function
from  itertools import tee, izip, ifilterfalse


def window(iterable,n):
    els = tee(iterable,n)
    for i,el in enumerate(els):
        for _ in range(i):
            next(el, None)
    return izip(*els)


def replace(iterable,placeholder=255):
    it = enumerate(iterable)

    def save_last(iterable):
        for i in iterable:
            yield i
        replace.last_index = i[0] #Save the last value
    it = save_last(it)

    it = ifilterfalse(lambda x: x[1]==placeholder, it)
    for i,(left,right) in enumerate(window(it,2)):
        if i==0:
            for j in range(left[0]):
                yield placeholder
        yield left[1]
        if right[0]>left[0]+1:
            if left[1]==right[1]:
                for _ in range(right[0]-left[0]-1):
                    yield left[1]
            else:
                for _ in range(right[0]-left[0]-1):
                    yield placeholder
    yield right[1]
    if right[0]<replace.last_index:
        for i in range(replace.last_index-right[0]):
            yield placeholder


a = [255,1,255,255,1,255,255,255,2,2,255,255,255,2,2,3,255,255,255,3,255,255]        
print('\nInput: {}'.format(a))
output = list(replace(a))
print('Proram output: {}'.format(output))
print('Goal output  : {}'.format([255,1,1,1,1,255,255,255,2,2,2,2,2,2,2,3,3,3,3,3,255,255]))

Здесь Я объясняю, как это работает.

0 голосов
/ 14 октября 2011

Более короткое решение на основе numpy:

import numpy
a = numpy.array([255,1,255,255,1,255,255,255,2,2,255,255,255,2,2,3,255,255,255,3])

b = [(i, numpy.argmax(a == i), len(a) - numpy.argmax(a[::-1] == i)) for i in numpy.unique(a[a < 255])]

for i in b:
    a[i[1]:i[2]] = i[0]

, где b - это список кортежей, состоящий из (unique value, start index, end index + 1).

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