我有一个 3D 数组,例如:
array = np.array([[[ 1., 1., 0.],
[ 0., 0., 0.],
[ 0., 0., 0.]],
[[1., 0., 0.],
[ 0., 0., 0.],
[ 0., 0., 0.]],
[[ 1., 0., 0.],
[ 0., 0., 0.],
[ 0., 0., 0.]]])
我需要为不同方向的每种可能尺寸找到连接的运行。 比如在(1,0,0)方向,水平方向,输出应该是:
> **Runs of size 1: 2
> **Runs of size 2: 1
> **Runs of size 3: 0
在 (0, 1, 0) 方向上,横跨纵轴:
> **Runs of size 1: 4
> **Runs of size 2: 0
> **Runs of size 3: 0
并且在 (0, 0, 1) 方向上,穿过 z 轴:
> **Runs of size 1: 1
> **Runs of size 2: 0
> **Runs of size 3: 1
有没有有效的方法来实现这个?
编辑:
我附上我正在处理的解决方案:
dire = np.array(([1, 0, 0], [0, 1, 0], [0, 0, 1])) # Possible directions
results = np.zeros((array.shape[0], len(dire))) # Maximum runs will be 3
# Find all indices
indices = np.argwhere(array == 1)
# Loop over each direction
for idire, dire in enumerate(dire):
results[0, idire] = np.count_nonzero(array) # Count all 1 (conection 0)
indices_to_compare = indices
# Now we compare the list of indices with a displaced list of indices
for irun in range(1, array.shape[0]):
indices_displaced = indices + dire*irun
aset = set([tuple(x) for x in indices_displaced])
bset = set([tuple(x) for x in indices_to_compare])
indices_to_compare = (np.array([x for x in aset & bset]))
results[irun, idire] = len(indices_to_compare)
# Rest the counts off bigger runs to the smaller ones, for duplicates
for indx in np.arange(array.shape[0]-2,-1,-1):
results[indx, idire] -=
np.sum(results[np.arange(array.shape[0]-1,indx,-1), idire])
print(results) # Each column is a direction, each row is the number of bins.
> [[ 2. 4. 3.]
[ 1. 0. 1.]
[ 1. 0. 0.]]
到目前为止,此代码不起作用,仅适用于方向 (0,1,0),没有任何联系且很简单。使用这种表示法,预期的输出应该是:
> [[ 2. 4. 1.]
[ 1. 0. 0.]
[ 0. 0. 1.]]
数组的比较来自this link .
编辑 2:
我对坐标的解释有误,似乎 np.argwhere
的结果 addint,(1,0,0) 超过了 z 轴,所以是预期的结果应该是:
> [[ 1. 4. 2.]
[ 0. 0. 1.]
[ 1. 0. 0.]]
最佳答案
这是一个沿轴向工作的矢量化解决方案:
def run_lengths(arr, axis):
# convert to boolean, for speed - no need to store 0 and 1 as floats
arr = arr.astype(bool)
# move the axis in question to the start, to make the slicing below easy
arr = np.moveaxis(arr, axis, 0)
# find positions at the start and end of a run
first = np.empty(arr.shape, dtype=bool)
first[:1] = arr[:1]
first[1:] = arr[1:] & ~arr[:-1]
last = np.zeros(arr.shape, dtype=bool)
last[-1:] = arr[-1]
last[:-1] = arr[:-1] & ~arr[1:]
# count the number in each run
c = np.cumsum(arr, axis=0)
lengths = c[last] - c[first]
# group the runs by length. Note the above gives 0 for a run of length 1,
# so result[i] is the number of runs of length (i + 1)
return np.bincount(lengths, minlength=len(arr))
for i in range(3):
print(run_lengths(array, axis=i))
[1 0 1]
[4 0 0]
[2 1 0]
关于python - 在给定方向的 3D 数组中查找连接元素(运行),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45210272/