从列索引向量中选择二维数组元素的向量



>我有一个 2D 数组 A:

28  39  52
77  80  66   
7   18  24    
9   97  68

和列索引 B 的向量数组:

1   
0   
2    
0

如何以pythonian的方式,使用基本的Python或Numpy,从A中选择与B中的列索引不对应的元素?

我应该得到这个包含 A 元素的 2D 数组,与存储在 B 中的列索引不对应:

28  52
80  66   
7   18    
97  68

您可以使用广播和逐行掩码为每行选择数组中未包含的元素:

设置

B = np.array([1, 0, 2, 0])
cols = np.arange(A.shape[1])

现在使用广播创建掩码,并为阵列编制索引。

mask = B[:, None] != cols
A[mask].reshape(-1, 2)

array([[28, 52],
[80, 66],
[ 7, 18],
[97, 68]])

我对你另一个问题的回答的衍生品,

使用列索引向量将 2D 数组元素替换为零

我们可以制作一个布尔mask,索引与之前使用的索引相同:

In [124]: mask = np.ones(A.shape, dtype=bool)                                                                           
In [126]: mask[np.arange(4), B] = False                                                                                 
In [127]: mask                                                                                                          
Out[127]: 
array([[ True, False,  True],
[False,  True,  True],
[ True,  True, False],
[False,  True,  True]])

使用布尔掩码索引数组会生成一维数组,因为在最一般的情况下,这种掩码可以在每行中选择不同数量的元素。

In [128]: A[mask]                                                                                                       
Out[128]: array([28, 52, 80, 66,  7, 18, 97, 68])

在这种情况下,结果可以改写回 2d:

In [129]: A[mask].reshape(4,2)                                                                                          
Out[129]: 
array([[28, 52],
[80, 66],
[ 7, 18],
[97, 68]])

由于您允许"基本Python",因此列表理解答案如下:

In [136]: [[y for i,y in enumerate(x) if i!=b] for b,x in zip(B,A)]                                                     
Out[136]: [[28, 52], [80, 66], [7, 18], [97, 68]]

如果其他A中的所有 0 都来自插入,那么我们也Out[127]mask可以用

In [142]: A!=0                                                                                                          
Out[142]: 
array([[ True, False,  True],
[False,  True,  True],
[ True,  True, False],
[False,  True,  True]])