我借了一些代码来实现一个函数来计算大量数据的运行中值。当前的一个对我来说太慢了(棘手的部分是,我需要从运行框中排除所有零)。下面是代码:
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)
if Mnow == 0:
return 0
else:
return np.median(sp)
def RunningMedian(seq, M):
seq = iter(seq)
s = []
# 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)
# 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
它工作得很好,唯一的缺点是速度太慢。有谁能帮我提高代码的效率?
在我探索了所有可能的方法之后,下面的简单代码可以比较有效地进行计算:
def RunningMedian(x,N):
idx = np.arange(N) + np.arange(len(x)-N+1)[:,None]
b = [row[row>0] for row in x[idx]]
return np.array(map(np.median,b))
#return np.array([np.median(c) for c in b]) # This also works
一种方法如下:
我发现了一个快得多的,复制如下:
看看链接:running_median
在处理数据样本时,可以使用两个heaps来维护数据样本的下半部分和上半部分。算法是这样的:对于每个值,将其放在一个适当的堆中,并“重新平衡”堆,以便它们的大小相差不超过1。然后,为了得到中间值,只需从更大的堆中取出第一个元素,或者取两个堆中第一个元素的平均值(如果它们大小相等)。此解决方案具有
O(n log(n))
时间复杂性。演示:
相关问题 更多 >
编程相关推荐