4.6.12 배열의 분리

4.6.12 유용한 함수 split()

① np.split() 개요

함수 np.split(ary)은 인자 ary를 여러 개의 부분 배열로 분리한다. 반환 값은 분리한 배열의 목록(list)이다.

numpy.split(ary, indices_or_sections, axis=0): 배열 ary를 축 axis에 따라 기준 indices_or_sections로 분할해 분할된 배열의 목록을 반환한다.

  • ary: 하위 배열로 분할할 배열
  • indices_or_sections: 정수 n인 경우, 배열은 축을 따라 n개의 동일한 배열로 분할되는데, 이러한 분할이 불가능하면 오류가 발생한다. 1차원 1D Array 또는 1차원 배열인 경우, indices_or_sections가 정렬된 정수의 1차원 배열인 경우, 해당 축을 따라 배열이 분할되는 위치를 나타낸다. 예를 들어, [2, 3]은 다음과 같이 ary[:2], ary[2:3], ary[3:]으로 분할된다. 첨자가 축을 따른 배열의 크기를 초과하는 경우 그에 따라 빈 하위 배열이 반환된다.
  • axis=0: 기본은 0이며, 분할하는 축

l = np.split(a, axis=0)는 다음에 학습할 np.vsplit(a)와 같다.

np.split(a, axis=0)과 np.vsplit(a)

l = np.split(a, axis=1)는 다음에 학습할 np.hsplit(a)와 같다.

np.split(a, axis=1)과 np.hsplit(a)

② np.split(ary, n)

다음 실수 9개로 구성된 벡터 x가 있다.

import numpy as np

x = np.arange(9.0)
x

출력:

array([0., 1., 2., 3., 4., 5., 6., 7., 8.])
s = np.split(x, 3)
s

출력:

[array([0., 1., 2.]), array([3., 4., 5.]), array([6., 7., 8.])]

np.split()의 결과는 분리된 배열 리스트이다.

print(type(s))
print(s[0])

출력:

<class 'list'>
[0. 1. 2.]

9개의 원소를 4개로 분리하면 동등하게 떨어지지 않아 오류가 발생한다.

np.split(x, 4)

오류:

ValueError: array split does not result in an equal division

③ np.split(ary, [i, j, k, …])

함수 np.split(a, [2, 6])으로 다음 그림처럼 10개의 요소로 구성된 배열을 원래 순서대로 각각 2, 4, 3개의 요소로 구성된 3개의 배열로 분리할 수 있다.

np.split(x, [2, 6])의 이해

여기서 [2, 6]이란 분할하는 첨자를 말한다. 즉 [2, 6]은 2, 6으로 구분하는 3개의 슬라이싱인 x[:2], x[2:6], x[6:]의 배열로 분할한다.

위 그림의 x는 다음과 같다.

x = np.arange(1, 10)
x

출력:

array([1, 2, 3, 4, 5, 6, 7, 8, 9])

다음 코드로 순서대로 원소가 2개, 4개, 3개인 배열로 분리할 수 있다.

np.split(x, [2, 6])

출력:

[array([1, 2]), array([3, 4, 5, 6]), array([7, 8, 9])]

원소 6개인 벡터 y가 있다.

y = np.arange(10, 61, 10)
y

출력:

array([10, 20, 30, 40, 50, 60])

함수 np.split(y, [2, 3, 4])로 분리하면 다음 그림처럼 첨자 2, 3, 4로 4개의 부분 배열로 반환된다.

np.split(y, [2, 3, 4])에서 인자 [2, 3, 4] 의미

다음은 위 그림을 구현한 코드이다.

np.split(y, [2, 3, 4])

출력:

[array([10, 20]), array([30]), array([40]), array([50, 60])]

다음 코드처럼 분할 첨자가 [2, 3, 4, 6]이면 마지막으로 분할되는 배열은 빈(empty) 배열이다. 그러므로 반환 목록 마지막이 array([], dtype=int32)이다.

np.split(y, [2, 3, 4, 6])

출력:

[array([10, 20]),
 array([30]),
 array([40]),
 array([50, 60]),
 array([], dtype=int32)]

위 결과를 확인하기 위해 슬라이싱 y[4:6]의 결과를 알아보자.

y[4:6]

출력:

array([50, 60])

이제 마지막 슬라이싱인 y[6:]의 결과를 알아보자. 바로 빈 배열임을 알 수 있다.

y[6:]

출력:

array([], dtype=int32)

④ 다차원 배열의 np.hsplit(ary, indices_or_sections)

다음 모양 (2, 12)의 2차원 배열 a가 있다.

a = np.arange(24).reshape(2, 12)
a

출력:

array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11],
       [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]])

배열 a를 축 1 방향(수평으로 이동하며)으로 3개로 분리하면 12/3 = 4이므로, 4개의 열로 구성된 분할 배열 목록인 다음 결과가 표시된다.

np.split(a, 3, axis=1)

출력:

[array([[ 0,  1,  2,  3],
        [12, 13, 14, 15]]),
 array([[ 4,  5,  6,  7],
        [16, 17, 18, 19]]),
 array([[ 8,  9, 10, 11],
        [20, 21, 22, 23]])]

마찬가지로, 배열 a를 축 1 방향으로 4개로 분리하면 다음 결과가 나온다.

np.split(a, 4, axis=1)

출력:

[array([[ 0,  1,  2],
        [12, 13, 14]]),
 array([[ 3,  4,  5],
        [15, 16, 17]]),
 array([[ 6,  7,  8],
        [18, 19, 20]]),
 array([[ 9, 10, 11],
        [21, 22, 23]])]

그러나, 배열 a를 축 1 방향으로 5개로 분리하면 12/5가 동등하게 떨어지지 않으므로 오류가 발생한다.

np.split(a, 5, axis=1)

오류:

ValueError: array split does not result in an equal division

다음은 슬라이싱 인자로 분리한 결과이다.

np.split(a, [3, 5, 8], axis=1)

출력:

[array([[ 0,  1,  2],
        [12, 13, 14]]),
 array([[ 3,  4],
        [15, 16]]),
 array([[ 5,  6,  7],
        [17, 18, 19]]),
 array([[ 8,  9, 10, 11],
        [20, 21, 22, 23]])]

참고로 직접 슬라이싱 a[:, :3]의 결과는 위 결과 첫 항목과 같다.

a[:, :3]

출력:

array([[ 0,  1,  2],
       [12, 13, 14]])

또한, 슬라이싱 a[:, 8:]의 결과는 위 결과 마지막 항목과 같다.

a[:, 8:]

출력:

array([[ 8,  9, 10, 11],
       [20, 21, 22, 23]])

다음은 모양 (6, 4)의 2차원 배열 b이다.

b = np.arange(24).reshape(6, 4)
b

출력:

array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15],
       [16, 17, 18, 19],
       [20, 21, 22, 23]])

배열 b를 축 0 방향(수직 방향)으로 3개로 나누면 다음 결과가 나온다. axis는 기본이 0이므로 생략 가능하다.

np.split(b, 3, axis=0)

출력:

[array([[ 0,  1,  2,  3],
        [ 4,  5,  6,  7]]),
 array([[ 8,  9, 10, 11],
        [12, 13, 14, 15]]),
 array([[16, 17, 18, 19],
        [20, 21, 22, 23]])]

축 0 방향(수직 방향)으로 슬라이싱 첨자 [2, 4, 6]으로 나누면 다음 결과가 나온다.

np.split(b, [2, 4, 6], axis=0)

출력:

[array([[ 0,  1,  2,  3],
        [ 4,  5,  6,  7]]),
 array([[ 8,  9, 10, 11],
        [12, 13, 14, 15]]),
 array([[16, 17, 18, 19],
        [20, 21, 22, 23]]),
 array([], shape=(0, 4), dtype=int32)]
서브목차