Programming Language/Python_library

파이썬_응용단계 ep.5 배열의 연결과 분할

A부터 시작하는 개발자. 아파테이아 2022. 12. 9. 19:53
320x100
서론

 

 

배열을 연결하는 부분에서는 다량의 실습용 코드들이 

등장하게 됩니다. 사실 이전부터 원래도 많긴 했지만 더욱 많아지게 됩니다!

 

이론을 열심히 배우는 것도 중요하겠습니다.

하지만 손으로 직접 쓰는 것만큼 더 좋은 공부방법도 없겠죠?!

 

직접 해보는 것과 열심히 보는 것은 다릅니다.

짜릿한 익스트림 자전거 처럼요!

 

자 먼저 concatenate 부터 시작합니다 🙌

 

 


 

배열의 연결

 

행의 수나 열의 수가 같은 두 개 이상의 배열을 연결하여 
더 큰 배열을 생성합니다.

 

리스트 자체는 + 연산자를 통해 합치는 것이 가능합니다.

 

[1,2] + [3,4]
[1, 2, 3, 4]

 

다만, 이를 ndarray에서 진행하면, 벡터화 연산이 되어

버립니다.

 

arr1 = np.arange(1,4)
arr2 = np.arange(4,7)
arr1, arr2
(array([1, 2, 3]), array([4, 5, 6]))

 

arr1+arr2
array([5, 7, 9])

 

그렇다면 어떻게 배열을 연결시킬 수 있을까요?

 

무려, 8가지나 되는 방법들이 있습니다.

 

먼저 concatenate ( n, axis)를 사용합니다.

 

arr = np.concatenate([arr1,arr2])
arr #1차원 배열 연결
array([1, 2, 3, 4, 5, 6])

 

concatenate

미국식[kɑnkǽtənèit] 영국식[kɔn-]발음

타동사 1 사슬같이 잇다; 연쇄시키다; <사건 등을> 결부[연결]시키다, 연관시키다

형용사 1 연쇄된, 이어진, 연결된

 

단어 자체가 연쇄시킨다는 뜻이죠.

 

2차원 배열의 연결도 가능할까요?

 

2차원 배열 연결

 

arr1 = np.arange(1,5).reshape(2,2)
#np.array([[1,2],[3,4]])
arr2 = np.arange(5,9).reshape(2,2)
#np.array([[5,6],[7,8]])
arr1, arr2
(array([[1, 2],
        [3, 4]]), array([[5, 6],
        [7, 8]]))

 

가능합니다.

위에서는 언급하지 않았지만 열/행의 기준을

수정시키는 것도 됩니다. axis를 사용해요.

 

arr = np.concatenate([arr1, arr2])
arr # 행을 기준으로 연결
array([[1, 2],
       [3, 4],
       [5, 6],
       [7, 8]])

 

arr = np.concatenate([arr1, arr2],axis= 1)
arr # 열을 기준으로 연결
array([[1, 2, 5, 6],
       [3, 4, 7, 8]])

 

자 행과 열을 붙인 것이 보이시나요?

 

그다음으로는 수평과 수직으로 붙이는 함수가 있습니다.

 

hstack

 

행의 수가 같은 두 개 이상의 배열을 으로 연결하여

열의 수가 늘어난 배열을 만듭니다.

 

🤔 연결할 배열은 하나의 리스트(튜플)에 담아서 메서드에 넣어줘야 합니다.

 

horizontal = 수평/ 가로
vertical = 수직/ 세로

hstack은 horizontal의 앞글자를 딴 것이죠!

 

직접 붙여보겠습니다.

 

a1 = np.ones((2,3)) # 2 x 3
a1

a2 = np.zeros((2,2)) # 2 x 2
a2
array([[1., 1., 1.],
       [1., 1., 1.]])
       
       
 array([[0., 0.],
       [0., 0.]])

 

np.hstack([a2,a1])
array([[0., 0., 1., 1., 1.],
       [0., 0., 1., 1., 1.]])

 

이렇게 수평으로 배열이 붙여지게 됩니다.

물론 좌우로 붙기 때문에, 행의 수는 같아야겠죠?

 

vstack

 

vstack도 hstack에 특별히 바뀌는 점은 없습니다.

수직으로 증가하게 됩니다.

 

b1 = np.ones((2,3)) # 2x3
b2 = np.zeros((3,3)) # 3x3

b1, b2
(array([[1., 1., 1.],
        [1., 1., 1.]]), 
 array([[0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]]))

 

원래 줄바꿈이 없지만, 보기 편하게 하기 위해

줄바꿈을 넣었습니다.

 

np.vstack([b1,b2])
array([[1., 1., 1.],
       [1., 1., 1.],
       [0., 0., 0.],
       [0., 0., 0.],
       [0., 0., 0.]])

 

수직으로 늘어납니다.

 

dstack

세번째 축, 깊이가 늘어납니다.

즉, 행이나 열이 아닌 depth가 늘어나는 방향으로 배열을 합칩니다

행렬을 보겠습니다.

 

c1 = np.ones((3,4))
c2 = np.zeros((3,4))
c1, c2
(array([[1., 1., 1., 1.],
        [1., 1., 1., 1.],
        [1., 1., 1., 1.]]), array([[0., 0., 0., 0.],
        [0., 0., 0., 0.],
        [0., 0., 0., 0.]]))

 

c1과 c2를 dstack으로 합쳐볼까요.

 

np.dstack([c1,c2])
array([[[1., 0.],
        [1., 0.],
        [1., 0.],
        [1., 0.]],

       [[1., 0.],
        [1., 0.],
        [1., 0.],
        [1., 0.]],

       [[1., 0.],
        [1., 0.],
        [1., 0.],
        [1., 0.]]])

 

자, 배열을 90도로 회전시킨 상태에서

합친 것처럼 3차원 배열로 합쳐졌습니다.

 

가장 안쪽의 원소의 차원이 증가합니다.

 

np.dstack([c1,c2]).shape
(3, 4, 2)

 

다른 stack들과 차이를 볼까요?

 

np.hstack([c1,c2])
array([[1., 1., 1., 1., 0., 0., 0., 0.],
       [1., 1., 1., 1., 0., 0., 0., 0.],
       [1., 1., 1., 1., 0., 0., 0., 0.]])

 

np.vstack([c1,c2])
array([[1., 1., 1., 1.],
       [1., 1., 1., 1.],
       [1., 1., 1., 1.],
       [0., 0., 0., 0.],
       [0., 0., 0., 0.],
       [0., 0., 0., 0.]])

 

그외의 stack도 있습니다.

 

stack

 

stack은 dstack의 기능을 확장한 것입니다!

dstack처럼 3차원 축으로 연결되는 것은 아니고

사용자가 지정한 축으로 배열을 연결합니다.

 

axis가 0일 때

c = np.stack([c1, c2])
c
array([[[1., 1., 1., 1.],
        [1., 1., 1., 1.],
        [1., 1., 1., 1.]],

       [[0., 0., 0., 0.],
        [0., 0., 0., 0.],
        [0., 0., 0., 0.]]])

 

shape 확인

 

c.shape
(2, 3, 4)

 

axis가 1일 때

 

c = np.stack([c1,c2], axis =1)
c, c.shape
(array([[[1., 1., 1., 1.],
         [0., 0., 0., 0.]],
 
        [[1., 1., 1., 1.],
         [0., 0., 0., 0.]],
 
        [[1., 1., 1., 1.],
         [0., 0., 0., 0.]]]), (3, 2, 4))

 

axis가 2일 때

(dstack과 유사합니다)

 

c = np.stack([c1,c2], axis =2)
c, c.shape
(array([[[1., 0.],
         [1., 0.],
         [1., 0.],
         [1., 0.]],
 
        [[1., 0.],
         [1., 0.],
         [1., 0.],
         [1., 0.]],
 
        [[1., 0.],
         [1., 0.],
         [1., 0.],
         [1., 0.]]]), (3, 4, 2))

 

r_ 인덱서

 

이 연결방법도 자주 쓰이는 방식입니다.

인덱서라는 특수한 메서드를 처음 선보이는데요?

 

hstack처럼 배열을 좌~우로 연결합니다.

다만 메서드 소괄호 "(  )" 를 사용하지 않고

대괄호 " [  ] " 을 사용합니다. (Bracket)

 

 

 

배열 생성

 

np.arange(1,4), np.arange(4,7)
(array([1, 2, 3]), array([4, 5, 6]))

 

np.r_[np.arange(1,4),np.arange(4,7)]
array([1, 2, 3, 4, 5, 6])

 

c_ 인덱서

r_ 인덱서와 다르게 배열의 차원을 올리고,

좌우로 연결합니다.

 

차원 증가시킴 → 그 후에 붙이는 것이죠

 

c = np.c_[np.arange(1,4),np.arange(4,7)]
c,c.shape
(array([[1, 4],
        [2, 5],
        [3, 6]]), (3, 2))

 

마지막 tile 입니다.

 

tile

 

tile은 동일한 배열을 반복해서 연결해주는데

배열과 횟수를 써주면 반복됩니다 (다른 배열을 쓰지 않습니다)

 

a = np.arange(6).reshape(2,-1)
a
array([[0, 1, 2],
       [3, 4, 5]])

 

np.tile(a,2) # 반복할 배열, 반복할 횟수
array([[0, 1, 2, 0, 1, 2],
       [3, 4, 5, 3, 4, 5]])

 

말 그대로 타일처럼 반복된 패턴을

배열로 깔아주는 것이죠!

 

np.tile(a,((3,2))) # 행으로 3번, 열로 2번
array([[0, 1, 2, 0, 1, 2],
       [3, 4, 5, 3, 4, 5],
       [0, 1, 2, 0, 1, 2],
       [3, 4, 5, 3, 4, 5],
       [0, 1, 2, 0, 1, 2],
       [3, 4, 5, 3, 4, 5]])

 

좋습니다.

연결의 반대기능인 분할 함수입니다.

 

배열 분할

split과 hsplit, vsplit을 사용합니다.

 

arr = np.arange(1,7)
arr
array([1, 2, 3, 4, 5, 6])

 

3개의 배열로 쪼개보겠습니다.

 

newarr = np.array_split(arr, 3)
newarr
[array([1, 2]), array([3, 4]), array([5, 6])]

 

2차원 배열부터는 연결했을때처럼,

vsplit과 hsplit으로 분할이 가능합니다.

 

arr = np.arange(1,13).reshape(3,4)
arr
array([[ 1,  2,  3,  4],
       [ 5,  6,  7,  8],
       [ 9, 10, 11, 12]])

 

split(배열, 쪼갤 횟수, 축의 기준 (0은 행, 1은 열)

newarr = np.array_split(arr,2,axis =1)
newarr
[array([[ 1,  2],
        [ 5,  6],
        [ 9, 10]]), array([[ 3,  4],
        [ 7,  8],
        [11, 12]])]

 

hsplit으로 똑같이 진행해보겠습니다.

 

np.hsplit(arr,2)
[array([[ 1,  2],
        [ 5,  6],
        [ 9, 10]]), array([[ 3,  4],
        [ 7,  8],
        [11, 12]])]

 

vsplit은 수평 방향으로 쪼개줍니다.

 

np.vsplit(arr,3)
[array([[1, 2, 3, 4]]), array([[5, 6, 7, 8]]), array([[ 9, 10, 11, 12]])]

 

이상입니다!

이렇게 해서 배열의 연결과 분할까지를 보았습니다.

 

다음에는 2차원 그리드 포인트, 기초적인 벡터화 연산을 다시 보겠습니다.

 

😇😇

728x90