Art*_*hur 5 python numpy scipy
假设我有一个 numpy 数组
a b c
A = i j k
u v w
Run Code Online (Sandbox Code Playgroud)
我想将值中心元素与其八个相邻元素中的一些元素(沿轴或沿对角线)进行比较。除了嵌套的 for 循环(对于大矩阵来说太慢)之外,还有什么更快的方法吗?
更具体地说,我想做的是将元素的值与其邻居进行比较并分配新值。
例如:
if (j == 1):
if (j>i) & (j>k):
j = 999
else:
j = 0
if (j == 2):
if (j>c) & (j>u):
j = 999
else:
j = 0
...
Run Code Online (Sandbox Code Playgroud)
像这样的东西。
您的操作包含许多条件,因此在一般情况下(任何类型的条件、任何类型的操作)执行此操作的最有效方法是使用循环。这可以使用 numba 或 cython 有效地完成。在特殊情况下,您可以使用 numpy/scipy 中的更高级别的函数来实现它。我将为您提供的特定示例展示一个解决方案,希望您可以从那里进行概括。
从一些假数据开始:
A = np.asarray([
[1, 1, 1, 2, 0],
[1, 0, 2, 2, 2],
[0, 2, 0, 1, 0],
[1, 2, 2, 1, 0],
[2, 1, 1, 1, 2]
])
Run Code Online (Sandbox Code Playgroud)
我们将找到A适用各种条件的位置。
查找A出现指定值的位置:
cond1a = A == 1
cond2a = A == 2
Run Code Online (Sandbox Code Playgroud)
这给出了大小与 相同的布尔值矩阵A。条件成立时该值为真,否则为假。
查找A每个元素与其邻居具有指定关系的位置:
# condition 1b: value greater than horizontal neighbors
f1 = np.asarray([[1, 0, 1]])
cond1b = A > scipy.ndimage.maximum_filter(
A, footprint=f1, mode='constant', cval=-np.inf)
# condition 2b: value greater than diagonal neighbors
f2 = np.asarray([
[0, 0, 1],
[0, 0, 0],
[1, 0, 0]
])
cond2b = A > scipy.ndimage.maximum_filter(
A, footprint=f2, mode='constant', cval=-np.inf)
Run Code Online (Sandbox Code Playgroud)
和以前一样,这给出了指示条件为真的布尔值矩阵。此代码使用scipy.ndimage.maximum_filter()。此函数迭代地将“足迹”移动到以 的每个元素为中心A。该位置的返回值是足迹为 1 的所有元素的最大值。该mode参数指定如何处理矩阵边界外的隐式值,其中足迹从边缘落下。在这里,我们将它们视为负无穷大,这与忽略它们相同(因为我们使用的是最大操作)。
根据条件设置结果的值。如果条件 1a 和 1b 都为真,或者条件 2a 和 2b 都为真,则值为 999。否则,值为 0。
result = np.zeros(A.shape)
result[(cond1a & cond1b) | (cond2a & cond2b)] = 999
Run Code Online (Sandbox Code Playgroud)
结果是:
[
[ 0, 0, 0, 0, 0],
[999, 0, 0, 999, 999],
[ 0, 0, 0, 999, 0],
[ 0, 0, 999, 0, 0],
[ 0, 0, 0, 0, 999]
]
Run Code Online (Sandbox Code Playgroud)
您可以通过更改过滤器覆盖区将此方法推广到其他邻居模式。您可以使用其他类型的过滤器(请参阅scipy.ndimage)推广到其他操作(最小值、中值、百分位数等)。对于可以表示为加权和的运算,请使用2d 互相关。
这种方法应该比在 python 中循环快得多。但是,它确实执行了不必要的计算(例如,只有当值为 1 或 2 时才需要计算最大值,但我们对所有元素都这样做)。手动循环可以避免这些计算。在 python 中循环可能比这里的代码慢得多。但是,在 numba 或 cython 中实现它可能会更快,因为这些工具会生成编译代码。
| 归档时间: |
|
| 查看次数: |
3955 次 |
| 最近记录: |