我正在寻求实现快速中位数,因为我必须为我的程序做很多中位数。我想使用python内置函数,因为它们会比我能做的更好。
我的中位数应该是: -提取5个值, -拆下中间一个, -找到其余4个值的中位数。
基本上多次调用:
numpy.median(np.array([0, 1, 2, 3, 4])[np.array([True, True, False, True, True])])
# (1. + 3.) / 2. = 2.0
我发现了两个函数:scipygeneric_filter和numpy位数_filter。我的问题是,即使他们似乎具有相同的参数,generic_filter也会提供正确的输出,而不是位数_filter。而且,generic_filter比中位数_filter慢。因此,我想知道我在对mnid_filter的调用中做错了什么,并将其用于速度目的。
import numpy as np
import scipy.ndimage as sc
v = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
print(sc.generic_filter(v, sc.median, footprint=np.array([1, 1, 0, 1, 1]), mode = "mirror", output=np.float64))
%timeit sc.generic_filter(v, sc.median, footprint=np.array([1, 1, 0, 1, 1]), mode = "mirror", output=np.float64)
print(sc.median_filter(v, footprint=np.array([1, 1, 0, 1, 1]), output=np.float64, mode="mirror"))
%timeit sc.median_filter(v, footprint=np.array([1, 1, 0, 1, 1]), output=np.float64, mode="mirror")
如您所见,generic_filter提供正确的输出: [1.5 1.5 2. 3. 4. 5. 6. 7. 7. 8.5 8.5] 每个循环327 µs±15.2 µs(平均±标准偏差,共运行7次,每个循环1000个)
和位数过滤器更快,但我不明白它的输出: [2。 2. 3. 4. 5. 6. 7. 7. 8. 9. 9. 9.] 每个循环12.4 µs±217 ns(平均±标准偏差,共运行7次,每个循环100000次)
你知道我的电话怎么了吗?
答案 0 :(得分:0)
唯一的区别似乎是由于处理“联系”的原因:
sc.median
返回平局的平均值sc.median_filter
似乎系统地返回了较大的值考虑到median_filter
is implemented的方式,对于“偶数个元素的中位数应返回均值”有效的情况,处理特殊/特殊情况很尴尬
我已经破解了处理这种情况的版本:
from scipy.ndimage.filters import _rank_filter
def median_filter(input, footprint, output=None, mode="reflect", cval=0.0, origin=0):
filter_size = np.where(footprint, 1, 0).sum()
rank = filter_size // 2
result = _rank_filter(
input, rank, None, footprint, output, mode, cval, origin, 'dummy')
if filter_size % 2 == 0:
if result is output:
tmp = result.copy()
else:
tmp = result
rank -= 1
assert rank > 0
result = _rank_filter(
input, rank, None, footprint, output, mode, cval, origin, 'dummy')
# fix up ties without creating any more garbage
result += tmp
result /= 2
return result
但是它有点笨拙,并且使用了scipy的内部功能(我正在使用1.3.0),因此将来可能会崩溃
在我的计算机上,这些基准为:
sc.generic_filter
每个循环耗时578 µs±8.51 µs sc.median_filter
每个循环耗时27.4 µs±1.37 µs median_filter
每次循环耗时65.6 µs±1.29 µs