2016-06-06 3 views
0

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

def RunningMedian(seq, M): 
    seq = iter(seq) 
    s = [] 
    m = M // 2 

    # Set up list s (to be sorted) and load deque with first window of seq 
    s = [item for item in islice(seq,M)] 
    d = deque(s) 
    # Simple lambda function to handle even/odd window sizes  
    median = lambda : s[m] if bool(M&1) else (s[m-1]+s[m])*0.5 
    # Sort it in increasing order and extract the median ("center" of the sorted window) 
    s.sort() 
    # remove zeros from the array 
    s = np.trim_zeros(s) 
    print s 
    medians = [median()] 
    for item in seq: 
     old = d.popleft()   # pop oldest from left 
     d.append(item)    # push newest in from right 
     del s[bisect_left(s, old)] # locate insertion point and then remove old 
     insort(s, item)   # insert newest such that new sort is not required   
     s = np.trim_zeros(s) 
     print s 
     medians.append(median()) 
    return medians 

Я тестирую код, но это не удалось. Мой пример: a = np.array([5 2 0 9 4 2 6 8]), я назвал эту функцию RunningMedian(a,3). Что я хочу для каждой рабочей коробки: [2,5] [2,9] [4,9] [2,4,9] [2,4,6] [2,6,8 ]

Однако, после того, как я назвал выше функцию, она дает: [2, 5] [2, 9] [4, 9] [2, 9] [2, 6] [2 , 8]

И также возвращает неправильные медианные значения. Возвращаемая медиана от вызова: [5, 9, 9, 9, 6, 8].

Кто-нибудь может помочь мне исправить эту проблему? Спасибо.

+0

Охота на импорт всегда отличная ... –

ответ

2

Основная проблема с вашим кодом, что выбрасывание нулей в s столовых с длиной объектов, используемой, что объясняет, почему вы не получите 3 длиной окна в конце ,

Предлагаю другой подход: используя правильную функцию для median и игнорируя эти нулевые значения локально. Таким образом, он чище, и вам не нужно trim_zeros (для этого очень плохое использование для импорта numpy). На основании вашей функции, вот что я придумал:

from itertools import islice 
from collections import deque 
from bisect import bisect_left,insort 

def median(s): 
    sp = [nz for nz in s if nz!=0] 
    print sp 
    Mnow = len(sp) 
    mnow = Mnow // 2 
    return sp[mnow] if bool(Mnow&1) else (sp[mnow-1]+sp[mnow])*0.5 

def RunningMedian(seq, M): 
    seq = iter(seq) 
    s = [] 
    m = M // 2 

    # Set up list s (to be sorted) and load deque with first window of seq 
    s = [item for item in islice(seq,M)] 
    d = deque(s) 
    ## Simple lambda function to handle even/odd window sizes  
    #median = lambda : s[m] if bool(M&1) else (s[m-1]+s[m])*0.5 

    # Sort it in increasing order and extract the median ("center" of the sorted window) 
    s.sort() 
    medians = [median(s)] 
    for item in seq: 
     old = d.popleft()   # pop oldest from left 
     d.append(item)    # push newest in from right 
     del s[bisect_left(s, old)] # locate insertion point and then remove old 
     insort(s, item)   # insert newest such that new sort is not required   
     medians.append(median(s)) 
    return medians 

Большая часть изменений в новой median функции, и я переехал отпечатки там. Я также добавил ваш импорт. Обратите внимание, что я бы подошел к этой проблеме совсем по-другому, и вполне возможно, что текущая «фиксированная» версия запахивает утиную ленту.

Во всяком случае, кажется, работает, как вы хотите, чтобы:

>>> a = [5, 2, 0, 9, 4, 2, 6, 8] 

>>> RunningMedian(a,3) 
[2, 5] 
[2, 9] 
[4, 9] 
[2, 4, 9] 
[2, 4, 6] 
[2, 6, 8] 
[3.5, 5.5, 6.5, 4, 4, 6] 

И причина, почему медианы были выключены в вашей версии было то, что соотношение окна определялась M, ширина окна ввода , Если вы отбросите нули, у вас появятся меньшие (четные) окна. В этом случае вам не нужен элемент middle (= second), но вам нужно усреднить два элемента в середине. Следовательно, ваш ошибочный вывод.

+1

Хорошо работает. Большое спасибо. –

0

попробовать:

[s[s!=0] for s in np.dstack((a[:-2], a[1:-1], a[2:]))[0]] 
Смежные вопросы