복붙노트

[PYTHON] 배열 블록 내에서 값의 합을 계산하는 방법

PYTHON

배열 블록 내에서 값의 합을 계산하는 방법

데이터 배열이 100x100 모양입니다. 나는 그것을 5x5 블록으로 나누고 각 블록은 20x20 격자를 갖고 싶다. 원하는 각 블록의 값은 그 블록의 모든 값의 합계입니다.

그것을 성취하기위한보다 우아한 방법이 있습니까?

x = np.arange(100)
y = np.arange(100)
X, Y = np.meshgrid(x, y)
Z = np.cos(X)*np.sin(Y)
Z_new = np.zeros((5, 5))
for i in range(5):
  for j in range(5):
    Z_new[i, j] = np.sum(Z[i*20:20+i*20, j*20:20+j*20])

이것은 인덱스를 기반으로합니다.

x = np.linspace(0, 1, 100)
y = np.linspace(0, 1, 100)
X, Y = np.meshgrid(x, y)
Z = np.cos(X)*np.sin(Y)
x_new = np.linspace(0, 1, 15)
y_new = np.linspace(0, 1, 15)

Z_new?

해결법

  1. ==============================

    1.각각의 두 축을 각각 모양 (5,20)으로 2 개로 분할하여 4D 배열을 만들고 길이 20 인 축을 따라 합을 줄이면됩니다.

    각각의 두 축을 각각 모양 (5,20)으로 2 개로 분할하여 4D 배열을 만들고 길이 20 인 축을 따라 합을 줄이면됩니다.

    Z_new = Z.reshape(5,20,5,20).sum(axis=(1,3))
    

    기능적으로 np.einsum과 동일하지만 잠재적으로 더 빠른 옵션 -

    Z_new = np.einsum('ijkl->ik',Z.reshape(5,20,5,20))
    

    일반 블록 크기

    일반적인 경우로 확대 -

    H,W = 5,5 # block-size
    m,n = Z.shape
    Z_new = Z.reshape(H,m//H,W,n//W).sum(axis=(1,3))
    

    einsum은 -

    Z_new = np.einsum('ijkl->ik',Z.reshape(H,m//H,W,n//W))
    

    블록의 평균 / 평균을 계산하려면 sum 메소드 대신 mean을 사용하십시오.

    일반 블록 크기 및 축소 작업

    감소를 위해 축과 함께 여러 축 매개 변수를 지원하는 ufuncs를 갖는 축소 연산을 사용하도록 확장하면,

    def blockwise_reduction(a, height, width, reduction_func=np.sum):
        m,n = a.shape
        a4D = a.reshape(height,m//height,width,n//width)
        return reduction_func(a4D,axis=(1,3))
    

    따라서 우리의 구체적인 경우를 해결하기 위해 그것은 다음과 같습니다 :

    blockwise_reduction(Z, height=5, width=5)
    

    블록 단위 평균 계산의 경우,

    blockwise_reduction(Z, height=5, width=5, reduction_func=np.mean)
    
  2. ==============================

    2.다음과 같이 할 수 있습니다.

    다음과 같이 할 수 있습니다.

    t = np.eye(5).repeat(20, axis=1)
    Z_new = t.dot(Z).dot(t.T)
    

    이는 Z_new [i, j] = t [i, k] * Z [k, l] * t [j, l]

    또한 Divakar 솔루션보다 빠릅니다.

  3. ==============================

    3.이러한 문제는 scipy.ndimage.measurements.sum과 같은 함수에 대해 "그룹화"및 "레이블 지정"용어를 사용할 수 있으므로 매우 좋은 후보입니다. 당신은 당신이 원하는 것을 다음과 같이 가질 것입니다 :

    이러한 문제는 scipy.ndimage.measurements.sum과 같은 함수에 대해 "그룹화"및 "레이블 지정"용어를 사용할 수 있으므로 매우 좋은 후보입니다. 당신은 당신이 원하는 것을 다음과 같이 가질 것입니다 :

    labels = [[20*(y//5) + x//5 for x in range(100)] for y in range(100)]
    s = scipy.ndimage.measurements.sum(Z, labels, range(400))
    

    (테스트되지는 않았지만 그 아이디어입니다).

  4. from https://stackoverflow.com/questions/36383107/how-to-evaluate-the-sum-of-values-within-array-blocks by cc-by-sa and MIT license