Python numpy矩阵中相邻元素的有效识别
我有一个100乘100的矩阵。该矩阵主要由零填充,但也包含一些整数。例如:Python numpy矩阵中相邻元素的有效识别,python,numpy,scipy,Python,Numpy,Scipy,我有一个100乘100的矩阵。该矩阵主要由零填充,但也包含一些整数。例如: [0 0 0 0 0 0 0 1] [0 2 2 0 0 0 0 0] [0 0 2 0 0 0 0 0] False [0 0 0 0 0 0 0 0] [0 3 3 0 0 0 0 0] 识别矩阵是否包含任意数量的不同类型的相邻整数的最有效方法是什么? 上面的示例将返回False。下面是一个真实的示例,其中显示了包含邻接的行: [0 0 0 0 0 0 0 1] [0 2 2 1 1 0 0 0] <-
[0 0 0 0 0 0 0 1]
[0 2 2 0 0 0 0 0]
[0 0 2 0 0 0 0 0] False
[0 0 0 0 0 0 0 0]
[0 3 3 0 0 0 0 0]
识别矩阵是否包含任意数量的不同类型的相邻整数的最有效方法是什么?
上面的示例将返回False。下面是一个真实的示例,其中显示了包含邻接的行:
[0 0 0 0 0 0 0 1]
[0 2 2 1 1 0 0 0] <---- True
[0 0 2 0 0 0 0 0]
[0 0 0 0 0 0 0 0]
[0 3 3 0 0 0 0 0]
我不需要确定邻接的位置,只需要确定它是否存在
目前,我最擅长的就是找到矩阵中的每个非零元素,然后检查其4个侧面元素
感谢您提供的所有精彩答案。查看您的问题描述,检查每个可能的非零整数值在数组中的位置,并查看是否存在交点,可能不需要太多计算工作。现在,这通常有些过分,但在您的规模上可能会奏效:您可以获得每个整数集合的索引,并使用
scipy.space.distance.cdist
计算它们的距离。我确信一些基于diff
或其他东西的智能解决方案更有效,但我还是很开心:
import numpy as np
from scipy.spatial.distance import cdist
from itertools import combinations
M1 = np.array(
[[0,0,0,0,0,0,0,1],
[0,2,2,1,1,0,0,0],
[0,0,2,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,3,3,0,0,0,0,0]])
M2 = np.array(
[[0,0,0,1,1,1,1,1],
[0,2,2,0,1,0,0,0],
[0,0,2,0,0,0,0,0],
[0,3,0,0,0,0,0,0],
[3,3,3,0,0,0,0,0]])
def overlaps_eh(M):
uniques = np.delete(np.unique(M),0) # get integers present
unival_inds = [np.transpose(np.where(M==unival)) for unival in uniques]
# unival_inds[k] contains the i,j indices of each element with the kth unique value
for i1,i2 in combinations(range(len(unival_inds)),2):
if np.any(cdist(unival_inds[i1],unival_inds[i2],'cityblock')==1):
return True
# if we're here: no adjacencies
return False
首先,我们将非零唯一矩阵元素收集到数组uniques
。然后,对于每个唯一值,我们找到输入数组中具有该值的每个元素的i,j
索引。然后,我们检查每对唯一值(使用itertools.compositions
生成),并使用scipy.space.distance.cdist
测量每对矩阵元素的成对距离。使用曼哈顿距离,如果任何一对元素的距离为1,则它们是相邻的。因此,如果这些距离中的任何一个为1,我们只需返回True
,否则我们将返回False
以下是使用
在最后一行,
diff
应用于屏蔽数组(忽略零个条目);diff
中的非零项表示数组a
中相邻的不同非零项。变量adjaccies
将具有邻接总数(可能您只想知道它是否为0)。在上面的示例中,它是1 这里有一种方法可以大量使用只关注性能的视图切片-
def distinct_ints(a):
# Mask of zeros, non-zeros as we would use them frequently
zm = a==0
nzm = ~zm
# Look for distint ints across rows
row_thresh = (nzm[:,1:] & zm[:,:-1]).sum(1)
row_out = ((nzm[:,1:] & (a[:,1:] != a[:,:-1])).sum(1)>row_thresh).any()
# Look for distint ints across cols
col_thresh = (nzm[1:] & zm[:-1]).sum(0)
col_out = ((nzm[1:] & (a[1:] != a[:-1])).sum(0)>col_thresh).any()
# Any from rows or cols
out = row_out | col_out
return out
如果您可以使用,这将非常容易使用,并且:
标签
默认为标签相邻值不同于0,不带对角线。然后,理解将与标签关联的所有值传递给helper函数,该函数检查是否存在多个唯一值。最后,它检查任何标签是否有多个值并返回该值
要在测试输入阵列上测试此功能,请执行以下操作:
arr1 = np.array([[0,0,0,0,0,0,0,1],
[0,2,2,1,1,0,0,0],
[0,0,2,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,3,3,0,0,0,0,0]])
arr2 = np.array([[0,0,0,1,1,1,1,1],
[0,2,2,0,1,0,0,0],
[0,0,2,0,0,0,0,0],
[0,3,0,0,0,0,0,0],
[3,3,3,0,0,0,0,0]])
arr3 = np.array([[0,0,0,0,0,0,0,1],
[0,2,2,0,0,0,0,0],
[0,0,2,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[0,3,3,0,0,0,0,0]])
>>> adjacent_diff(arr1)
True
>>> adjacent_diff(arr2)
False
>>> adjacent_diff(arr3)
False
使用
numpy.diff
可以实现这一点,但是,不应该考虑零的事实使事情变得复杂了一点
可以将零设置为足够大或足够小的值,以避免出现问题:
a[a == 0] = -999
或者使用浮点数组并将其设置为nan
或inf
:
a[a == 0] = numpy.nan
然后只需在每个方向上查找1
的一阶差:
numpy.any(numpy.abs(numpy.diff(a, axis=0)) == 1) or numpy.any(numpy.abs(numpy.diff(a, axis=1)) == 1)
在不发布完整答案的情况下,我将从带有axis参数的
numpy.diff
开始。谢谢,这将显著减少搜索区域。能否添加检查每个元素的代码。这可能会消除一些关于测试的模糊性。
a[a == 0] = -999
a[a == 0] = numpy.nan
numpy.any(numpy.abs(numpy.diff(a, axis=0)) == 1) or numpy.any(numpy.abs(numpy.diff(a, axis=1)) == 1)