代码之家  ›  专栏  ›  技术社区  ›  Huanian Zhang

不含零的运行中值

  •  0
  • Huanian Zhang  · 技术社区  · 8 年前

    我借用了一些代码来计算数组的运行中值。但对于每个正在运行的数组,我想排除零值。代码如下:

    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]

    谁能帮我纠正这个问题?非常感谢。

    2 回复  |  直到 5 年前
        1
  •  2
  •   Andras Deak -- Слава Україні    5 年前

    代码的主要问题是在 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
    

    大部分变化发生在新的 中值的 我把指纹移到了那里。我还添加了您的进口。请注意,我处理这个问题的方式非常不同,很可能当前的“固定”版本有点像鸭子胶带。

    无论如何,它似乎可以按您的意愿工作:

    >>> 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 ,输入窗口宽度。如果您放弃零,您将得到更小的(偶数长度)窗口。在这种情况下,您不需要中间(=秒)元素,但需要平均在中间的两个元素。因此,输出错误。

        2
  •  0
  •   piRSquared    8 年前

    尝试:

    [s[s!=0] for s in np.dstack((a[:-2], a[1:-1], a[2:]))[0]]