【问题标题】:Replace (every) element in a list by the median of the nearest neighbors用最近邻居的中位数替换列表中的(每个)元素
【发布时间】:2018-05-14 20:23:05
【问题描述】:

我有一个数组A,比如说:

import numpy as np
A = np.array([1,2,3,4,5,6,7,8])

我希望通过将A 中的每个元素替换为其四个最近邻居的中值来创建一个新数组B,不考虑给定位置的值.. . 例如:

B[2] = np.median([A[0], A[1], A[3], A[4]]) (=3) 

问题是我需要在巨大的A 上执行此操作,并且我想优化时间,所以我想避免 for 循环或类似的情况。而且...我不在乎边缘的结果。

我已经尝试过scipy.ndimage.filters.median_filter,但它没有产生所需的输出:

import scipy.ndimage
B = scipy.ndimage.filters.median_filter(A,footprint=[1,1,0,1,1],mode='wrap')

产生B=[7,4,4,5,6,7,6,6],这显然不是正确的答案。 欢迎任何想法。

【问题讨论】:

  • 你如何计算最近的 4 个邻居?价值观是否不同?这是一个相当简单的问题,可以在O(n lg n) 中完成
  • 听起来像一个内核操作:docs.scipy.org/doc/scipy-0.14.0/reference/generated/… - 或者你想在图像上进行傅立叶变换/乘法/反向傅立叶之后/之后做的事情

标签: python numpy vectorization median


【解决方案1】:

可能正在使用np.roll 移动数组中的数字,例如:

A_1 = np.roll(A,1)
# output: array([8, 1, 2, 3, 4, 5, 6, 7])

然后滚动 -2、-1 和 2 也是一样的:

A_2 = np.roll(A,2)
A_m1 = np.roll(A,-1)
A_m2 = np.roll(A,-2)

现在您只需对 4 个数组求和,因为对于每个索引,您在其中一个中有 4 个邻居:

B = (A_1 + A_2 + A_m1 + A_m2)/4.

正如你所说,你不关心边缘,我认为它对你有用!

编辑:我想我是专注于将均值和中位数混合起来的滚动想法,中位数可以通过B = np.median([A_1,A_2,A_m1,A_m2],axis=0)计算得到

【讨论】:

  • 就是这个意思。
  • 对于中位数,您必须将这四个数组堆叠起来,然后沿右轴计算中位数。
  • Median 将获取值数组,为它们提供所有适当的数组编号,并找到中心值。示例:Array[0] 为最小值,Array[4] 为最大值,将 Array[2] 作为中位数。
  • 确实,那么做np.median([A_1,A_2,A_m1,A_m2],axis=0)是中值?
  • 是的。这是平均值,但它很接近!正确的方法是: B = np.median([np.roll(A,-2),np.roll(A,-1),np.roll(A,1),np.roll(A,2) ],axis=0) 谢谢 =)
【解决方案2】:

我会在 pandas 中创建一个长度为 5 的滚动中心窗口,并将中值函数应用于窗口的值,中间的值被屏蔽掉:

import numpy as np
A = np.array([1,2,3,4,5,6,7,8])

mask = np.array(np.ones(5), bool)
mask[5//2] = False

import pandas as pd
df = pd.DataFrame(A)

r5 = df.rolling(5, center=True)

result = r5.apply(lambda x: np.median(x[mask]))

result
     0
0  NaN
1  NaN
2  3.0
3  4.0
4  5.0
5  6.0
6  NaN
7  NaN

【讨论】:

  • 天哪……完全正确。我将对其进行编辑以解决所提出的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-10
  • 1970-01-01
  • 1970-01-01
  • 2020-01-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多