【问题标题】:Multi dimensional Indexing with Numpy使用 Numpy 进行多维索引
【发布时间】:2020-05-20 15:10:42
【问题描述】:

我使用的是 3 维数组,其定义如下:

x = np.zeros((dim1, dim2, dim3), dtype=np.float32)

插入一些数据后,只有在特定列中的值仍然为零时,我才需要应用一个函数。 我感兴趣的列是由这个包含正确索引的数组选择的

scale_idx = np.array([0,1,3])

因此我要做的是使用索引来选择那些行和列。

起初我尝试这样做,前二维使用布尔掩码,第三维使用数组:

x[x[:,:,scale_idx].any(axis =2)] ,scale_idx]

但我收到此错误:

IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (2,) (2,) (3,) 

如果我将最后一个索引更改为 : 我会得到我感兴趣的所有行,但我会得到所有可能的列,我希望最后一个数组将充当索引器,如 @987654321 中所述@。

x[x[:,:,scale_idx].any(axis =2)]

我的scale_idx 应该被解释为列索引器,但实际上被解释为行索引,因此,由于只有 2 行符合条件,但我有 3 个索引,我得到一个 IndexError

我找到了一种解决方法,使用

x[x[:,:,scale_idx].any(axis =2)][:,:,scale_idx]

但它有点难看,因为它是一个切片,我无法修改原始数组。

有人愿意向我解释我做错了什么吗?

编辑: 感谢@hpaulj,我设法隔离了我需要的单元格,之后我创建了一个与所选值具有相同形状的矩阵,并将这些值分配给被屏蔽的单元格,令我惊讶的是,新值不是我刚刚设置的那些是一些我无法弄清楚它们来自哪里的随机整数。 重现代码:

scale_idx = np.array([0,3,1])
b = x[:,:,scale_idx].any(axis =2)
I, J = np.nonzero(b)
x[I[:,None], J[:,None], scale_idx] #this selects the correct cells
>>>
array([[ 50,  50,  50],
     [100, 100, 100],
     [100, 100, 100]])
scaler.transform(x[I[:,None], J[:,None], scale_idx]) #sklearn standard scaler, returns a matrix with the scaled values
>>>
array([[-0.50600345, -0.5445559 , -1.2957878 ],
     [-0.50600345, -0.25915199, -1.22266904],
     [-0.50600345, -0.25915199, -1.22266904]]) 
x[I[:,None], J[:,None], scale_idx] = scaler.transform(x[I[:,None], J[:,None], scale_idx]) #assign the new values to the selected cells
x[I[:,None], J[:,None], scale_idx] #check the new values

array([[0, 2, 0],
     [0, 6, 2],
     [0, 6, 2]])

为什么新值与我的预期不同?

【问题讨论】:

  • 您能分享一个具有特定尺寸的虚拟示例吗?很难说 20 岁的人该做什么
  • 对不起,那个20不应该出现,我已经重构了一点代码,现在应该更清楚了,我仍然无法弄清楚为什么它不起作用。也许不支持布尔掩码加数组索引器?
  • 您不能将int 的值设置为浮点数

标签: python arrays numpy multidimensional-array indexing


【解决方案1】:

让我们以 indexing 文档中的 3d 布尔掩码示例为例:

In [135]: x = np.arange(30).reshape(2,3,5) 
     ...: b = np.array([[True, True, False], [False, True, True]])                             
In [136]: x                                                                                    
Out[136]: 
array([[[ 0,  1,  2,  3,  4],
        [ 5,  6,  7,  8,  9],
        [10, 11, 12, 13, 14]],

       [[15, 16, 17, 18, 19],
        [20, 21, 22, 23, 24],
        [25, 26, 27, 28, 29]]])
In [137]: b                                                                                    
Out[137]: 
array([[ True,  True, False],
       [False,  True,  True]])
In [138]: x[b]                                                                                 
Out[138]: 
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [20, 21, 22, 23, 24],
       [25, 26, 27, 28, 29]])

这是一个二维数组。掩码 b 从前 2 个维度中选择元素。 False 值导致它跳过 [10...] 和 [15...] 行。

我们可以对最后一个维度进行切片:

In [139]: x[b,:3]                                                                              
Out[139]: 
array([[ 0,  1,  2],
       [ 5,  6,  7],
       [20, 21, 22],
       [25, 26, 27]])

但列表索引会产生错误(除非它的长度为 4):

In [140]: x[b,[0,1,2]]                                                                         
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-140-7f1dbec100f2> in <module>
----> 1 x[b,[0,1,2]]

IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (4,) (4,) (3,) 

原因是布尔掩码有效地转换为带有np.where 数组的索引:

In [141]: np.nonzero(b)                                                                        
Out[141]: (array([0, 0, 1, 1]), array([0, 1, 1, 2]))

nonzero 找到 4 个非零元素。那么x[b] 索引是:

In [143]: x[[0,0,1,1],[0,1,1,2],:]                                                             
Out[143]: 
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [20, 21, 22, 23, 24],
       [25, 26, 27, 28, 29]])

https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#boolean-array-indexing

然后形状不匹配变得更加明显:

In [144]: x[[0,0,1,1],[0,1,1,2],[1,2,3]]                                                       
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-144-1efd76049cb0> in <module>
----> 1 x[[0,0,1,1],[0,1,1,2],[1,2,3]]

IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (4,) (4,) (3,) 

如果列表大小匹配,则索引会运行,但会生成“对角线”,而不是块:

In [145]: x[[0,0,1,1],[0,1,1,2],[1,2,3,4]]                                                     
Out[145]: array([ 1,  7, 23, 29])

正如您发现的那样,两阶段索引有效 - 但不适用于设置值

In [146]: x[[0,0,1,1],[0,1,1,2]][:,[1,2,3]]                                                    
Out[146]: 
array([[ 1,  2,  3],
       [ 6,  7,  8],
       [21, 22, 23],
       [26, 27, 28]])

我们可以通过“转置”最后一个索引列表来获取块:

In [147]: x[[0,0,1,1],[0,1,1,2],[[1],[2],[3]]]                                                 
Out[147]: 
array([[ 1,  6, 21, 26],
       [ 2,  7, 22, 27],
       [ 3,  8, 23, 28]])

好的,这是转置。我们可以对其应用转置。或者我们可以先转置b 数组:

In [148]: I,J=np.nonzero(b)                                                                    
In [149]: x[I[:,None], J[:,None], [1,2,3]]                                                     
Out[149]: 
array([[ 1,  2,  3],
       [ 6,  7,  8],
       [21, 22, 23],
       [26, 27, 28]])

这适用于设置

In [150]: x[I[:,None], J[:,None], [1,2,3]]=0                                                   
In [151]: x                                                                                    
Out[151]: 
array([[[ 0,  0,  0,  0,  4],
        [ 5,  0,  0,  0,  9],
        [10, 11, 12, 13, 14]],

       [[15, 16, 17, 18, 19],
        [20,  0,  0,  0, 24],
        [25,  0,  0,  0, 29]]])

答案很长。我对正在发生的事情有一个大致的了解,但需要弄清楚细节。另外,您需要了解发生了什么。

【讨论】:

  • 非常感谢您的广泛回答,我已经设法使用转置技巧使用布尔索引并且它有效。但我仍然无法正确设置新值,我已经用新信息更新了我的问题。
猜你喜欢
  • 1970-01-01
  • 2018-11-07
  • 1970-01-01
  • 2018-01-22
  • 1970-01-01
  • 1970-01-01
  • 2015-08-16
  • 1970-01-01
  • 2016-03-08
相关资源
最近更新 更多