scipy 通过在Numpy中求平均值或类似方法缩小3D矩阵

5cnsuln7  于 2022-11-10  发布在  其他
关注(0)|答案(3)|浏览(163)

有没有一种简单的方法可以通过在 NumpyScipy 中平均一定大小的块来减小3D矩阵的大小,甚至使用NetCDF工具或类似的工具?我不久前用stride写了一个2D矩阵,但一个现成的函数会有很大帮助。

编辑:

我希望输入和输出的外观示例:
Input's shape: (500, 500, 100)
Calling the function: downsize(input, 10, 10, 10, func)
Output's shape: (50, 50, 10),其中每个单元格的值是func在连续的10x10x10子矩阵上的结果。
可替换地,代码可以获得期望的矩阵大小作为输入,而不是子矩阵的大小,并且计算出它们。
谢谢

waxmsbnn

waxmsbnn1#

这里有一种方法,使用整形将每个轴分成两个,从而创建六个轴,然后对三个原始轴中的每个轴的第二个切片轴执行合并平均,以获得块平均-

def blockwise_average_3D(A,S):    
    # A is the 3D input array
    # S is the blocksize on which averaging is to be performed

    m,n,r = np.array(A.shape)//S
    return A.reshape(m,S[0],n,S[1],r,S[2]).mean((1,3,5))

样品运行-

In [107]: A = np.random.randint(0,255,(500,500,100)) # 3D Input array
     ...: S = (10,10,10)                             # Blocksize
     ...: 

In [108]: out = blockwise_average_3D(A,S)

In [109]: out[0,0,0]
Out[109]: 124.242

In [110]: A[:10,:10,:10].mean()
Out[110]: 124.242

In [111]: out[0,1,0]
Out[111]: 129.89400000000001

In [112]: A[:10,10:20,:10].mean()
Out[112]: 129.89400000000001
tkqqtvp1

tkqqtvp12#

对于记录,下面是一个适用于N维数组的函数,一般化为Divakar's answer

import numpy as np

def blockwise_average_ND(a, factors):    
    """
    `a` is the N-dim input array
    `factors` is the blocksize on which averaging is to be performed
    """

    factors = np.asanyarray(factors)
    sh = np.column_stack([a.shape//factors, factors]).ravel()
    b = a.reshape(sh).mean(tuple(range(1, 2*a.ndim, 2)))

    return b

示例

a = np.arange(192).reshape(4, 6, 8)
blockwise_average_ND(a, (2, 3, 4))

# array([[[ 33.5,  37.5],

# [ 57.5,  61.5]],

# [[129.5, 133.5],

# [153.5, 157.5]]])

a = np.arange(135).reshape(15, 9)
blockwise_average_ND(a, (5, 3))

# array([[ 19.,  22.,  25.],

# [ 64.,  67.,  70.],

# [109., 112., 115.]])
mkshixfv

mkshixfv3#

我最终把我的2维版本扩展到了3维,显然它很有效。在这里,以防别人也需要它。

import numpy as np
from numpy.lib.stride_tricks import as_strided

# 3D version of my block view function

def block_view(arr, block_size):
    shape   = tuple(_shape / _bsize for _shape, _bsize in zip(arr.shape, block_size)) + block_size
    strides = tuple(_bsize * _stride for _bsize, _stride in zip(block_size, arr.strides)) + arr.strides

    return as_strided(arr, shape=shape, strides=strides)

def aggregate(arr, block_size):
    blocks = block_view(arr, block_size)
    dimension_offset = len(arr.shape)
    block_dimensions = range(dimension_offset, dimension_offset + len(block_size))
    for dim in block_dimensions:
        blocks = np.mean(blocks, axis=dim, keepdims=True)

    blocks = blocks[:, :, :, 0, 0, 0]
    return blocks

我试着让它对任何N维矩阵都有效,但唯一的限制是blocks = blocks[:, :, :, 0, 0, 0]线。

相关问题