如何分配通过解压缩triu_indices获得的numpy切片视图

时间:2019-08-16 18:51:56

标签: python numpy

我试图根据使用triu_indices获得的索引将值分配给4张量的切片。但是,我只能为切片视图分配值,而不能为基础数据分配值。

我用过这篇文章

How to unpack a tuple when indexing?

获得4x4x4x4张量的6x6切片。我看过很多文章,可以在其中为数组切片分配数据,但是我不清楚为什么我的语法无法实现此目的。

import numpy as np
t_vec = np.ones(6,6)
n_occs = 4
n_nnoccs = 4
t2 = np.zeros((n_noccs, n_noccs, n_occs, n_occs)).astype(np.float)
O = (np.triu_indices(n_occs, 1)) 
t2[O][(slice(None),) + V] = t_vec
t2[V][(slice(None),) + O] = t_vec

预期结果是将t2的256个条目中的72个替换为1。实际输出是原始的0矩阵。

1 个答案:

答案 0 :(得分:1)

triu_indices编制索引会产生一个副本;这些索引是由where函数产生的,并执行高级索引编制:

In [40]: x = np.arange(9).reshape(3,3)                                                                       
In [41]: idx = np.triu_indices(3)                                                                            
In [42]: idx                                                                                                 
Out[42]: (array([0, 0, 0, 1, 1, 2]), array([0, 1, 2, 1, 2, 2]))
In [43]: x[idx]                                                                                              
Out[43]: array([0, 1, 2, 4, 5, 8])

请注意,Out[43]是一维数组-从x中选择的值。

我们可以使用标量或兼容数组(1d)直接为其分配:

In [44]: x[idx] = 0                                                                                          
In [45]: x                                                                                                   
Out[45]: 
array([[0, 0, 0],
       [3, 0, 0],
       [6, 7, 0]])
In [46]: x[idx] = np.arange(1,7)                                                                             
In [47]: x                                                                                                   
Out[47]: 
array([[1, 2, 3],
       [3, 4, 5],
       [6, 7, 6]])

但是我们不能添加另一层索引。

在您的4d情况下:

In [56]: t2 = np.arange(4**4).reshape(4,4,4,4)    

t2[idx]产生一个(6,4,4)数组,一个副本。下一层索引将产生(6,6):

In [57]: t2[idx][:,idx[0],idx[1]]                                                                            
Out[57]: 
array([[ 17,  18,  19,  22,  23,  27],
       [ 33,  34,  35,  38,  39,  43],
       [ 49,  50,  51,  54,  55,  59],
       [ 97,  98,  99, 102, 103, 107],
       [113, 114, 115, 118, 119, 123],
       [177, 178, 179, 182, 183, 187]])

如果我两次应用idx的2个元素,我将得到对角(6,6):

In [58]: t2[idx[0],idx[1],idx[0],idx[1]]                                                                     
Out[58]: array([ 17,  34,  51, 102, 119, 187])

我可以一步完成4d索引编制:

In [59]: t2[idx[0][:,None],idx[1][:,None],idx[0],idx[1]]                                                     
Out[59]: 
array([[ 17,  18,  19,  22,  23,  27],
       [ 33,  34,  35,  38,  39,  43],
       [ 49,  50,  51,  54,  55,  59],
       [ 97,  98,  99, 102, 103, 107],
       [113, 114, 115, 118, 119, 123],
       [177, 178, 179, 182, 183, 187]])

我可以为其分配值,然后修改t2

In [60]: t2[idx[0][:,None],idx[1][:,None],idx[0],idx[1]]=0                                                   
In [61]: t2                                                                                                  
Out[61]: 
array([[[[  0,   1,   2,   3],
         [  4,   5,   6,   7],
         [  8,   9,  10,  11],
         [ 12,  13,  14,  15]],

        [[ 16,   0,   0,   0],
         [ 20,  21,   0,   0],
         [ 24,  25,  26,   0],
         [ 28,  29,  30,  31]],
    ....