Select Numpy 数组中每一列都满足某些条件的所有行

Select all rows from Numpy array where each column satisfies some condition

我有一个 x 形式的数组,

x = [[1,2,3,...,7,8,9],
[1,2,3,...,7,9,8],
...,
[9,8,7,...,3,1,2],
[9,8,7,...,3,2,1]]

我还为每一列设置了一组 不允许的 数字。我想 select 所有在每列中只允许使用字符的行。例如,我可能只想要第一列中没有任何 [1,2,3] 的行;我可以做到这一点,

x[~np.in1d(x[:,0], [1,2,3])]

对于任何 单个 列,我都可以做到这一点。但我希望一次对 所有 列执行此操作,select 仅对每个元素都是其列的允许数字的行进行处理。我似乎无法 x.anyx.all 做好这件事 - 我应该怎么做?

编辑:澄清一下,每列的不允许数字是不同的。实际上,我会有一些数组 y,

y = [[1,4,...,7,8],
[2,5,...,9,4],
[3,6,...,8,6]]

我想要来自 x 的行,其中第 1 列不能在 [1,2,3] 中,第 2 列不能在 [4,5,6] 中,依此类推。

可以broadcast比较,然后all检查:

x[(x != y[:,None,:]).all(axis=(0,-1))]

细分:

# compare each element of `x` to each element of `y`
# mask.shape == (y.shape[0], x.shape[0], x.shape[1])
mask = (x != y[:,None,:])

# `all(0)` checks, for each element in `x`, it doesn't match any element in the same column of `y`
# `all(-1) checks along the rows of `x`
mask = mask.all(axis=(0,-1)

# slice
x[mask]

例如,考虑:

x = np. array([[1, 2],
       [9, 8],
       [5, 6],
       [7, 8]])

y = np.array([[1, 4],
       [2, 5],
       [3, 7]])

然后mask = (x != y[:,None,:]).all(axis=(0,1))给出

array([False,  True,  True,  True])

最近建议使用 np.isin 而不是 np.in1d。这让您 (a) 一次比较整个数组,并且 (b) 更有效地反转掩码。

x[np.isin(x, [1, 2, 3], invert=True).all(1)]

np.isin 保留 x 的形状,因此您可以在列中使用 .all。它还有一个 invert 参数,允许您执行与 ~isin(x, [1, 2, 3]) 等效的操作,但效率更高。

此解决方案将与其他解决方案所建议的计算类似的计算向量化得更有效(尽管它仍然是线性搜索),并且也避免创建临时数组。