在2D中显示4D矩阵的更多“ pythonic”方式

时间:2019-05-25 01:50:28

标签: python numpy reshape

我想将4d矩阵绘制为具有索引的2d矩阵:

[i][j][k][l] --> [i * nj + j][ k * nl + l]

我有一个有效的版本here

这是我想要的,但是不是很优雅。我研究了“重塑”,但这并不是我想要的,或者我使用不正确。

给出一个形状为(100000,4)的4d数组“ r”,我要替换的相关代码段为:


def transform(i,j,k,l, s1, s2):
    return [i * s1 + j, k * s2 + l]

nx = 5
ny = 11
iedges=np.linspace(0,100, nx)
jedges=np.linspace(0, 20, ny)
bins = ( iedges,jedges,iedges,jedges )

H, edges = np.histogramdd(r, bins=bins )

H2 = np.zeros(( (nx-1)*(ny-1),(nx-1)*(ny-1)))
for i in range(nx-1):
    for j in range(ny-1):
        for k in range(nx-1):
            for l in range(ny-1):
                x,y = transform(i,j,k,l,ny-1,ny-1)                
                H2[x][y] = H[i][j][k][l]

在这种情况下,H2的值将与H的值相对应,但是条目

i,j,k,l
将显示为
i*ny + j, k * ny + l

示例图:

4d matrix represented as 2d matrix

2 个答案:

答案 0 :(得分:0)

您似乎可以从i,j,k,l计算出x,y?类似于:

from functools import partial

def get_ijkl(x, y, s1, s2):
    # "Reverse" of `transform`
    i, j = divmod(x, s1)
    k, l = divmod(y, s2)
    return (i, j, k, l)


def get_2d_val(x, y, s1, s2, four_dim_array):
    return four_dim_array[get_ijkl(x, y, s1, s2)]


smaller_shape = ((nx-1)*(ny-1), (nx-1)*(ny-1))

知道这有几种可能的方法:

H3 = np.fromfunction(
    partial(get_2d_val, s1=ny-1, s2=ny-1, four_dim_array=H),
    shape=smaller_shape,
    dtype=int,
)
assert np.all(H2 == H3)
indices_to_take = np.array([
    [list(get_ijkl(x, y, ny-1, ny-1)) for x in range(smaller_shape[0])] for y in range(smaller_shape[1])
]).transpose()
H4 = H[tuple(indices_to_take)]
assert np.all(H2 == H4)
  • 正如@hpaulj回答的那样,您可以简单地对数组进行整形,它将更快。但是,如果您有一些不同的transform并可以计算适当的“反向”函数,则使用fromfunction或自定义索引将非常有用

答案 1 :(得分:0)

您确定reshape无效吗?

我在一个小的随机r上运行了您的代码。 H的非零项是:

In [13]: np.argwhere(H)                                                                                  
Out[13]: 
array([[0, 9, 3, 1],
       [1, 1, 1, 2],
       [1, 2, 1, 3],
       [2, 2, 2, 3],
       [3, 1, 1, 8]])

以及转换后的H2

In [14]: np.argwhere(H2)                                                                                 
Out[14]: 
array([[ 9, 31],
       [11, 12],
       [12, 13],
       [22, 23],
       [31, 18]])

H索引之一通过以下方式转换为H2索引:

In [16]: transform(0,9,3,1,4,10)                                                                         
Out[16]: [9, 31]

如果仅重塑H,我将得到与H2相同的数组:

In [17]: H3=H.reshape(40,40)                                                                             
In [18]: np.argwhere(H3)                                                                                 
Out[18]: 
array([[ 9, 31],
       [11, 12],
       [12, 13],
       [22, 23],
       [31, 18]])
In [19]: np.allclose(H2,H3)                                                                              
Out[19]: True

因此,在不深入研究代码细节的情况下,对我来说,它看起来像是简单的重塑。