NumPy中的多维布尔数组索引

6

我有两个二维数组,一个是数字类型,另一个是布尔值类型:

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

idx = 
array([[False, False, False, False, False, False, False, False, False, False],
       [False,  True,  True,  True,  True,  True, False, False, False, False],
       [False,  True,  True,  True,  True,  True, False, False, False, False],
       [False,  True,  True,  True,  True,  True, False, False, False, False],
       [False, False, False,  True,  True,  True,  True, False, False, False],
       [False, False, False, False,  True,  True,  True, False, False, False],
       [False, False, False, False, False, False,  True, False, False, False],
       [False, False, False, False, False, False, False,  True, False, False],
       [False, False, False, False, False, False, False, False, False, False],
       [False, False, False, False, False, False, False, False, False, False]], dtype=bool)

当我对数组进行索引时,它返回一个一维数组:
x[idx]
array([ 1.,  1.,  1.,  1.,  1.,  2.,  2.,  2.,  2.,  2.,  3.,  3.,  3.,
    3.,  3.,  4.,  4.,  4.,  4.,  5.,  5.,  5.,  6.,  7.])

我该如何索引数组并返回期望输出的二维数组:
x[idx]
array([[ 1.,  1.,  1.,  1.,  1.],
       [ 2.,  2.,  2.,  2.,  2.],
       [ 3.,  3.,  3.,  3.,  3.],
       [ 4.,  4.,  4.,  4.],
       [ 5.,  5.,  5.],
       [ 6.],
       [ 7.]])
2个回答

4
您的命令返回一个一维数组,因为不可能在不破坏通常需要的列结构的情况下实现。例如,您请求输出中的7原先属于第7列,现在它在第0列;而且,据我所知,numpy不支持在同一维度上具有不同大小的高维数组。我的意思是,numpy不能有一个数组,其前三行长度为5,第四行长度为4等等——所有行(相同维度)需要具有相同的长度。
我认为您能得到的最好结果是一个数组的数组(而不是二维数组)。这是我将如何构建它,尽管可能还有更好的方法我不知道:
In [9]: from itertools import izip
In [11]: array([r[ridx] for r, ridx in izip(x, idx) if ridx.sum() > 0])
Out[11]: 
array([array([ 1.,  1.,  1.,  1.,  1.]), array([ 2.,  2.,  2.,  2.,  2.]),
       array([ 3.,  3.,  3.,  3.,  3.]), array([ 4.,  4.,  4.,  4.]),
       array([ 5.,  5.,  5.]), array([ 6.]), array([ 7.])], dtype=object)

差不多了,但还差一点,不过我已经想通了。 - camdenl
2
@camdenl,你所拥有的是一个列表数组,而不是问题中要求的2D numpy数组。无论如何,我认为使用array([r[ridx].tolist() for r, ridx in izip(x, idx) if ridx.sum() > 0])比使用enumerate更易读。 - Korem
你说得没错,但我必须将结构作为2D numpy数组,所以我认为两者都不是正确的解决方案。 - camdenl
我刚才意识到你说的不可能,所以我认为根据使用情况,提出的任何一种解决方案都是有效的。 - camdenl

0

编辑:这将创建一个列表的数组

np.array([val[idx[i]].tolist() for i,val in enumerate(x) if len(val[idx[i]].tolist()) > 0])

array([[1.0, 1.0, 1.0, 1.0, 1.0], 
   [2.0, 2.0, 2.0, 2.0, 2.0],
   [3.0, 3.0, 3.0, 3.0, 3.0], 
   [4.0, 4.0, 4.0, 4.0], 
   [5.0, 5.0, 5.0],
   [6.0], 
   [7.0]], dtype=object)

2
这是一个列表的一维数组,而不是所要求的二维数组。因此它并没有“工作”,但可以使用一个变通方法。 - Korem

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接