我有一个二维Numpy数组,包含从0到n的值。 我想获取一个长度为n的列表,以使该列表的第i个元素是值i + 1(不包括0)的所有索引的数组。
例如,对于输入
array([[1, 0, 1],
[2, 2, 0]])
我希望得到
[array([[0, 0], [0, 2]]), array([[1,0], [1,1]])]
我发现了以下相关问题: Get a list of all indices of repeated elements in a numpy array 这可能会有所帮助,但我希望找到一个更直接的解决方案,该解决方案不需要对数组进行展平和排序,并且尽可能高效。
答案 0 :(得分:3)
您可以首先获取数组中的非零元素,然后在列表推导中使用argwhere
为每个非零元素获取单独的数组。 np.unique(arr[arr!=0])
在这里将为您提供非零元素,您可以在这些元素上进行迭代以获得索引。
arr = np.array([[1, 0, 1],
[2, 2, 0]])
indices = [np.argwhere(arr==i) for i in np.unique(arr[arr!=0])]
# [array([[0, 0],
# [0, 2]]), array([[1, 0],
# [1, 1]])]
答案 1 :(得分:3)
这是向量化方法,适用于任意数量维的数组。此解决方案的想法是扩展np.unique
中return_index
方法的功能,并返回一个数组数组,每个数组都包含n维索引,给定numpy数组中唯一值的出现。>
对于更紧凑的解决方案,我在以下各个步骤中定义了以下功能以及一些解释。
def ndix_unique(x):
"""
Finds the indices where each unique
value in x is found
----------
x: np.array
Can have multiple dimensions
Returns
-------
- 1darray of sorted unique values
- Array of arrays. Each array contains the indices where a
given value in x is found, where the values are sorted
"""
# flattens x. Both will be necessary
x_ = x.ravel()
# Sort y using np.argsort
ix_ = np.argsort(x_)
# Finds the indices in x_ that result in the
# unique array. Used later on to split
u, s = np.unique(x_[ix_], return_index=True)
# Mapping of the 1D indices to n-dimensional
# indices taking the shape of x as a reference
ix_ndim = np.unravel_index(ix_, x.shape)
# Stack these as columns
ix = np.column_stack(ix_ndim) if x.ndim > 1 else ix_
# Split the nD coordinates using the indices in s
# i.e. where the changes of values take place
return u, np.split(ix, s[1:])
让我们首先使用建议的ndarray
检查结果:
a = np.array([[1, 0, 1],[2, 2, 0]])
vals, ixs = ndix_unique(a)
print(vals)
array([0, 1, 2])
print(ixs)
[array([[0, 1],
[1, 2]]),
array([[0, 0],
[0, 2]]),
array([[1, 0],
[1, 1]])]
让我们尝试其他情况:
a = np.array([[1,1,4],[2,2,1],[3,3,1]])
vals, ixs = ndix_unique(a)
print(vals)
array([1, 2, 3, 4])
print(ixs)
array([array([[0, 0],
[0, 1],
[1, 2],
[2, 2]]),
array([[1, 0],
[1, 1]]),
array([[2, 0],
[2, 1]]),
array([[0, 2]])], dtype=object)
现在让我们尝试使用 1D
数组:
a = np.array([1,5,4,3,3])
vals, ixs = ndix_unique(a)
print(vals)
array([1, 3, 4, 5])
print(ixs)
array([array([0]), array([3, 4]), array([2]), array([1])], dtype=object)
最后一个带有 3D
ndarray的示例:
a = np.array([[[1,1,2]],[[2,3,4]]])
vals, ixs = ndix_unique(a)
print(vals)
array([1, 2, 3, 4])
print(ixs)
array([array([[0, 0, 0],
[0, 0, 1]]),
array([[0, 0, 2],
[1, 0, 0]]),
array([[1, 0, 1]]),
array([[1, 0, 2]])], dtype=object)