【发布时间】:2016-10-06 21:18:31
【问题描述】:
我借用了一些代码,试图实现一个函数来计算大量数据的运行中位数。当前的对我来说太慢了(棘手的部分是我需要从运行框中排除所有零)。下面是代码:
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
【问题讨论】:
-
如果您将此问题移至 Code Review Stack Exchange,您可以获得更多答案。
-
Running or sliding median, mean and standard deviation 不适合您,还是太慢了,无法满足您的需求?
-
看看this。这是很多代码,用 Python 编写可能不会那么快。但是实现的速度差不多,它使用与 pandas 进行滚动中位数计算相同的方法,但为了速度是用 Cython 编写的。
-
为什么不使用 pandas.rolling_* 方法?