如果输出数组中的顺序不相关,那么您可能只使用Eelco Hoogendoorn's answer。但是,如果您想保持与原始数组中相同的相对顺序,这是另一种可能的方法。
import numpy as np
a = np.array([
[1, 0, 1, 0],
[0, 0, 1, 1],
[1, 0, 1, 0],
[0, 0, 1, 1],
[1, 1, 1, 0],
[1, 1, 1, 0],
[1, 1, 1, 0],
[1, 1, 1, 0],
])
idx = np.array([0, 2, 3, 4, 6, 7])
# Make an array of row numbers
r = np.arange(len(a))
# Replace row numbers in idx with -1
# (use assume_unique only if indices in idx are unique)
r[np.isin(r, idx, assume_unique=True)] = -1
# Add the column to the array
a2 = np.concatenate([a, r[:, np.newaxis]], axis=-1)
# Find unique indices and inverse indices
_, uniq_idx, inv_idx = np.unique(a2, return_index=True, return_inverse=True, axis=0)
# Sort indices to make output array and inverse indices
s = np.argsort(uniq_idx)
a_uniq = a[uniq_idx[s]]
inv_idx = s[inv_idx]
print(a_uniq)
# [[1 0 1 0]
# [0 0 1 1]
# [0 0 1 1]
# [1 1 1 0]
# [1 1 1 0]]
print(np.all(a_uniq[inv_idx] == a))
# True
编辑:一些进一步的解释。
上述解决方案中的想法是应用np.unique,但在某种程度上,idx 中未包含的行不受其影响。为此,您只需在每一行中添加一个新数字。对于idx 中包含的行,此编号将始终为-1,而对于其余行,每个行将是不同的编号。这样一来,np.unique 不可能删除不在idx 中的行。为此,我构建了r,首先使用np.arange(len(a)),它为每行提供一个数字:
[0 1 2 3 4 5 6 7]
然后我检查哪些在idx 和np.isin(r, idx, assume_unique=True) 中(assume_unique 只能在idx 中的元素保证是唯一的情况下使用),所以r[np.isin(r, idx, assume_unique=True)] = -1 将把所有索引idx进入-1:
[-1 1 -1 -1 -1 5 -1 -1]
作为新列添加到a 到a2:
[[ 1 0 1 0 -1]
[ 0 0 1 1 1]
[ 1 0 1 0 -1]
[ 0 0 1 1 -1]
[ 1 1 1 0 -1]
[ 1 1 1 0 5]
[ 1 1 1 0 -1]
[ 1 1 1 0 -1]]
现在只需将np.unique 应用于a2。正如预期的那样,只有idx 中的行可能会被删除。但是,由于我们要保持原来的相对顺序,我们不能使用np.unique 的输出,因为它是排序的。我们使用return_index 和return_inverse 来获取构成唯一行数组的索引和使您返回原始数组的索引,并实际丢弃新数组。
要形成最终的数组,您需要对uniq_idx 进行排序以保持相对顺序,然后对inv_idx 进行相应的排序。 np.argsort 为您提供将uniq_idx 排序为s 的索引。 uniq_idx[s] 只是排序后的唯一行索引数组,s[inv_idx] 会将inv_idx 中的每个反向索引映射到resorted 数组中的相应索引。所以,最后,a[uniq_idx[s]] 为您提供了输出数组,而新的inv_idx 将您带回原来的数组。