首页 > 解决方案 > 在 2d 中显示 4d 矩阵的更多“pythonic”方式

问题描述

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

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

这里有一个工作版本。

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

给定一个形状为 (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 矩阵表示为 2d 矩阵

标签: pythonnumpyreshape

解决方案


看起来你可以i,j,k,lx,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或自定义索引将变得有用

推荐阅读