본문 바로가기

Programming Language/Python_library

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

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