我有一维标签数组。索引i的对象具有标签标签[i]。我还有一个数组或列表数组,其中我有我想要访问的标签索引。 例如:
labels = np.array([2, 0, 3, 3, 0, 0, 0, 0, 0, 0])
duplicates = np.array(np.array([0,3]), np.array([3,0]), np.array([6,7,8]))
我想访问标签元素,因此输出看起来像这样:
labels_duplicates = np.array(np.array([2,3]), np.array([3,2]), np.array([0,0,0]))
实现这一目标的最佳方法是什么(最好没有for循环)?
我想要实现的目标:我有一系列中心索引(重复)。我必须检查这些中心的标签是否匹配。如果他们这样做,中心将合并为一个中心。如果有比上面更好的解决方案,我很高兴听到它。
答案 0 :(得分:1)
首先让我们专注于做(不要担心'循环'):
In [82]: duplicates = [np.array([0,3]), np.array([3,0]), np.array([6,7,8])]
In [83]: [labels[x] for x in duplicates]
Out[83]: [array([2, 3]), array([3, 2]), array([0, 0, 0])]
我将duplicates
列为一个列表,而不是数组。 dtype对象的1d数组仅仅是一个列表。 (但要么在这里工作)
(np.concatenate(duplicates)
解决方案移至结束)
只要您的duplicates
元素的长度不同,就没有一种方法(我能想到)可以避免“循环”,迭代这些元素。这只是numpy
索引的本质。 2d操作本质上是“矩形”。如果有一个直接执行它的函数,它可能隐藏了一个循环。
如果只有少数duplicates
更长,并且您不介意失去额外的'值,你可以剪辑它们:
labels[np.array([x[:2] for x in duplicates])]
array([[2, 3],
[3, 2],
[0, 0]])
同样,您可以将每个duplicate
扩展为相同的长度。这是一个通用np.pad
功能,但它可能提供比您需要的更多选项。
对于填充,目标长度需要理解,作为填充本身。 np.pad
可用于复制最后一个值。另一种选择是默认或虚拟索引(例如0
)。
mlen = max([len(x) for x in duplicates])
padded_dups = [np.pad(x,(0,mlen-len(x)),'edge') for x in duplicates]
labels[np.array(padded_dup)]
array([[2, 3, 3],
[3, 2, 2],
[0, 0, 0]])
duplicates
应该是列表还是对象数组?可能并不重要。
[labels[x] for x in np.array(duplicates)]
的工作原理。如您所知,np.array(duplicates)-1
有效,而列表需要[x-1 for x in duplicates]
。
在初步时间中,两次减法大约需要相同的时间,这意味着对象数组减法执行相当于列表理解。
像这样的数组有时像列表一样,在其他情况下就像2d数组。这是一个发展领域,所以你必须逐个尝试。
array([array([0, 3]), array([3, 0]), array([6, 7, 8])], dtype=object)
之前我展示过您可以轻松获得标签的平面列表:
flat_labels = labels[np.concatenate(duplicates)]
# array([2, 3, 3, 2, 0, 0, 0])
我刚刚意识到np.split
很容易将这样的数组拆分成你想要的子数组:
split_indices = np.cumsum([len(x) for x in duplicates])[:-1]
np.split(flat_labels,split_indices)
# [array([2, 3]), array([3, 2]), array([0, 0, 0])]