무효 클릭 IP 추적 중...
머신러닝,딥러닝/넘파이,numpy

[넘파이 기초] vstack | hstack | concatenate | dstack | stack 마스터

꼬예 2021. 5. 13.
[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터

오늘은 array들을 합치는데 사용되는 다양한 api에 대해 알아보겠습니다. 

 

 

 

vstack vs hstack

1차원 벡터끼리의 결합

import numpy as np

a = np.random.randint(0, 10, (4,)) # 1차 벡터
b = np.random.randint(0, 10, (4,)) # 1차 벡터

print(f"a: {a.shape}\n{a}")
print(f"a: {b.shape}\n{b}\n")

vstack = np.vstack([a, b]) 
hstack = np.hstack([a, b]) 

print(f"vstack: {vstack.shape}\n{vstack}")
print(f"hstack: {hstack.shape}\n{hstack}\n")

 

output :

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - vstack vs hstack

a, b는 각각 4개의 원소를 가진 1차원 벡터 입니다.

우리는 여기서 vstack과 hstack를 이용해 두 배열을 합치려고 합니다. 

 

여기서 vstackvertical stack수직방향으로 쌓는다는 의미이고, hstackhorizontal stack수평방향으로 쌓는 다는 의미입니다.

 

사용방법은 vstack/hstack 인자로 리스트튜플과 함께 값을 넣어주면됩니다. 여기선 리스트안에 각각의 벡터를 a , b 변수로 받아 집어 넣었습니다. 

 

참고사항으로 수학에서는 벡터를 column 벡터를 기본으로 간주하지만 데이터사이언스에는 row벡터를 기본으로 설정합니다. 

 

이러한 이유로 넘파이에선 기본적으로 1차원벡터를 row 벡터라고 가정을 하지요.

 

즉 vstack을 이용해 수직으로 쌓는다면 오른쪽이 아닌 왼쪽같이 쌓인다는 말이죠.

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - vstack vs hstack

마찬가지로 hstack 을 이용하면  오른쪽이 아닌 왼쪽 처럼 쌓아 나가게 됩니다. 

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - vstack vs hstack

2차원 벡터끼리의 결합

import numpy as np

a = np.random.randint(0, 10, (1,4)) # row 벡터
b = np.random.randint(0, 10, (1,4)) # row 벡터

print(f"a: {a.shape}\n{a}")
print(f"a: {b.shape}\n{b}\n")

vstack = np.vstack((a, b)) # 튜플 사용
hstack = np.hstack((a, b)) 

print(f"vstack: {vstack.shape}\n{vstack}")
print(f"hstack: {hstack.shape}\n{hstack}\n") 

output :

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - vstack vs hstack

2차원 벡터터부터는 shap을 통해 row, 또는column 벡터를 명확하게 지정해줄 수 있습니다.

a, b 각각 (1,4)의 shape인 row 벡터로 만들었습니다.

 

앞선 1차원 벡터끼리의 결합과 차원은 다르지만 같은 row 벡터임으로 합칠때도 같은 모양으로 작동합니다.

(다만 차원이 하나 높아졌기때문에 대괄호 하나가 더 추가된것을 확인할 수 있습니다.)

 

 

이번엔 컬럼 벡터를 만들어볼까요?

import numpy as np

a = np.random.randint(0, 10, (4,1)) # column 벡터
b = np.random.randint(0, 10, (4,1)) # column 벡터

print(f"a: {a.shape}\n{a}")
print(f"a: {b.shape}\n{b}\n")

vstack = np.vstack((a, b)) 
hstack = np.hstack((a, b)) 

print(f"vstack: {vstack.shape}\n{vstack}")
print(f"hstack: {hstack.shape}\n{hstack}\n") 
#

output :

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - vstack vs hstack

output을 보면 어떤식으로 기능하는지 아실 수 있을 겁니다.

 

1차원 벡터와 2차원 행렬 결합(서로다른 차원의 결합)

 import numpy as np

a = np.random.randint(0, 10, (3,4)) # matrix
b = np.random.randint(0, 10, (4,)) # row 벡터

print(f"a: {a.shape}\n{a}")
print(f"a: {b.shape}\n{b}\n")

vstack = np.vstack([a, b]) 

print(f"vstack: {vstack.shape}\n{vstack}")

output :

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - vstack vs hstack

 

(3,4)의 matrix와 (4,) row벡터와 결합입니다. 즉 둘 사이의 차원이 다른 경우입니다.

이때는 vstack만 사용 가능합니다. 

앞서 배운대로 1차원 벡터는 row벡터를 가정합니다. 

그렇기 때문에 hstack 실행할경우 아래와 같은 이상한 모습이 되죠.

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - vstack vs hstack

과감하게 합쳐보시면.. ValueError(all the input arrays must have same number of dimensions...)를 만나게 됩니다. 

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - vstack vs hstack

다음 코드는 올바르게 실행이 될까요?

 import numpy as np

a = np.random.randint(0, 10, (3,4)) # matrix
b = np.random.randint(0, 10, (3,)) # row 벡터

print(f"a: {a.shape}\n{a}")
print(f"a: {b.shape}\n{b}\n")

vstack = np.hstack([a, b]) 

print(f"vstack: {vstack.shape}\n{vstack}")

output :

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - vstack vs hstack

역시나 ValueError 가 발생합니다. 왜냐하면 앞서 말씀드렸듯이 b가 row 벡터이기 때문에 아래와 같이 이상한 모양으로 합쳐지게되기 때문입니다.  

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - vstack vs hstack

a 의 row 열과 b의 배열의 수를 같게 했다고해서.. 넘파이에서 알아서 연산을 하지 않는다는 것을 확인했습니다. 

 

그러면 어떻게해야할까요?

reshape을 통해 직접 row벡터를  column 벡터로 변경을 해주면됩니다. 

 import numpy as np

a = np.random.randint(0, 10, (3,4)) # matrix
b = np.random.randint(0, 10, (3,)) # row 벡터

print(f"a: {a.shape}\n{a}")
print(f"a: {b.shape}\n{b}\n")

hstack = np.hstack([a, b.reshape(-1,1)]) # 컬럼 벡터로 변경


print(f"hstack: {hstack.shape}\n{hstack}\n")

output :

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - vstack vs hstack

for loop을 이용한 배열 쌓기

 

vstack과 hstack은 for문과도 함께 자주 쓰이는데요! 

쓰임새를 같이 확인해보겠습니다. 

 

import numpy as np 

dataset = np.empty((0, 4))
print(f"initial shape: {dataset.shape}\n")

for iter in range(5):
    data_sample = np.random.uniform(0, 5, (1, 4))
    dataset = np.vstack((dataset, data_sample))
    print(f"iter/shape: {iter}/{dataset.shape}")

output :

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - vstack vs hstack

 

우선 for문을 이용할때는 vstack 안에 들어가는 인자 모습이 조금 다른걸 알 수 있습니다. 

이전에는 리스트나, 튜플을 적고 그안에 배열들을 적었었죠?

하지만 이번 예시에서는 첫번째 인자로 빈 array(empty 이용) , 그 다음 인자에는 그 빈 array에 넣을 값을 의미 합니다. 

 

빈 array는  empty를 이용해서 만드는데요, row를 0으로 설정했다는 의미는 row방향으로 쌓겠다는 의미를 나타냅니다. column 에 4는 크기 4로 고정하겠다는 의미구요.

 

즉 정리하면 0은 고정된 숫자가 아니라 우리가 for문을 통해 바꿀 숫자입니다.

 

코드를 보시면 vstack를 통해 row방향으로 하나씩 쌓아가면서 shape이 어떻게 변해가는지 충분히 이해하실 수 있을 겁니다. 

 

그렇다면 hstack은 어떻게 쓸까요?

import numpy as np 

dataset = np.empty((4, 0))
print(f"initial shape: {dataset.shape}\n")

for iter in range(5):
    data_sample = np.random.uniform(0, 5, (4, 1))
    dataset = np.hstack((dataset, data_sample))
    print(f"iter/shape: {iter}/{dataset.shape}")
    

output :

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - vstack vs hstack

이번에는 empty를 (4,0) 즉 row를 4 열로 고정하고 column을 0으로 설정함으로써 column방향으로 쌓겠다는것을 의미합니다. 

 

마찬가지로 hstack를 통해 shape이 변해가는모습을 보면 충분히 이해하실 수 있을 겁니다. 

 

하지만 이와 같은 방식은 대량의 데이터를 다를 경우 연산 속도가 느려 효율성이 떨어지는 경향이 있습니다. 

 

그렇다면 어떻게 작성하는것이 더 효율적인 방법일까요? 

아래 코드를 보시죠!

 

import numpy as np

dataset_tmp = list()
for iter in range(100):
    data_sample = np.random.uniform(0, 5, (1, 4))
    dataset_tmp.append(data_sample)
    
dataset = np.vstack(dataset_tmp)
print(f"final shape: {dataset.shape}")

output :

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - vstack vs hstack

우선 앞선 예와 다르고 empty가 아닌 그냥 빈 리스트를 만듭니다. 

여기서는 dataset_tmp라는 빈리스트를 만들었습니다. 

 

그리고 앞서와 마찬가지로 for문을 도는데요.

1바퀴 돌때마다 append를 통해 array들을 쌓아 나갑니다.

 

for문이 끝나면 리스트안에 array들이 쌓여있는 상태가 됩니다. 

이 모습 뭔가 익숙하지 않으신가요?

 

네 맞습니다. 제일 처음에 봤던 형태 vstack/hstack 안에 리스트를 넣고 그안에 배열을 넣은 형태입니다.

for문을 이용은 했지만 제일 처음봤던 방법으로 모든 값들을 합치는 것이지요.

 

이번 예에서는 vstack 을 통해 수직방향으로 쌓았습니다.  

 

 

 

concatenate

영어로 연결시키다라는 뜻을 가진 concatenate는 그 뜻대로 합치는 기능을 합니다.

앞서 배운 vstack과 hstack보다 좀 더 general한 api로 봐주시면 되는데요!

코드를 통해 확인해 보겠습니다. 

import numpy as np

a = np.random.randint(0, 10, (3,))
b = np.random.randint(0, 10, (4,))

concat = np.concatenate([a,b])
concat0 = np.concatenate([a, b], axis = 0)

print(f"a: {a.shape}\n {a}")
print(f"a: {b.shape}\n {b}\n")

print(f"concat.shape: {concat.shape}\n {concat}")
print(f"concat0.shape: {concat0.shape}\n {concat0}\n")

 

output :

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - concatenate

사용법은 vstack, hstack과 마찬가지로 인자에 리스트 형태로 배열의 뭉치를 넣습니다.

차이점이 있다면 vstack, hstack처럼 합치는 방향이 이미 정해진것이 아니라 axis 를 통해 합칠 방향을 직접 정해줄 수 있다는 것입니다. 

(axis 개념이 낯설거나 어려우신분들은 이전 포스팅 axis 편을 참고해주시기 바랍니다.)

 

a, b는 1차원 벡터로  axis 가 하나(여기선 axis = 0, column 방향)밖에 없으니 사실상 axis가 의미가 없습니다.

(axis를 지정하지 않을 경우 디폴트로 가장 바깥차원의 방향을 의미하는 axis = 0 이 설정됩니다. )

1차원 벡터는 concat 을 하면 그냥 오른쪽으로 붙힌다라고 생각하시면 됩니다.

 

위코드에서 디폴트 설정과 axis=0이 같은 값으로 출력되는것을 확인할 수 있습니다.

 

 

다음은 2차원 행렬끼리 연산을 보겠습니다.

import numpy as np

a = np.random.randint(0, 10, (1,3))
b = np.random.randint(0, 10, (1,3)) # row 벡터/ 위에서는 벡터 ndarray였다면 여기선 행렬 ndarray


axis0 = np.concatenate([a,b], axis = 0) # row 방향  # >> 여기선 vertical stack과 동일하게 작용
axis1 = np.concatenate([a, b], axis = 1) # column 방향 # >> 여기선 horizontal stack과 동일하게 작용
axis_n1 = np.concatenate([a, b], axis = -1) # 1이랑 똑같은거임

print(f"a: {a.shape}\n {a}")
print(f"b: {b.shape}\n {b}\n")

print(f"axis0.shape: {axis0.shape}\n {axis0}")
print(f"axis1.shape: {axis1.shape}\n {axis1}")
print(f"axis_n1.shape: {axis_n1.shape}\n {axis_n1}")

output :

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - concatenate

2차원이기 때문에 axis 가 두개(axis = 0, axis =1) 이 사용 가능합니다. 

 

여기선 a, b가 2차원 row 벡터 형태인데요.

output을 보시면 aixs 방향에 따라 어떻게 합쳐지는지 감이 오실 겁니다.  

 

참고로 axis =1이 가장 안쪽 차원 즉 가장 마지막 차원이기 때문에 axis = -1 로도 대체 가능하다는 점도 확인하시기 바랍니다:)

 

shape가 서로 다른 행렬의 연산

이번에 shape이 다를때는 어떤것을 조심해야 하는지 확인해 보겠습니다.

import numpy as np

a = np.random.randint(0, 10, (3,4))
b = np.random.randint(0, 10, (3,2))

concat = np.concatenate([a,b], axis = 1) # column 방향으로 합치겠다는것.

print(f"a: {a.shape}\n {a}")
print(f"b: {b.shape}\n {b}\n")

print(f"concat.shape: {concat.shape}\n {concat}")

output :

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - concatenate

 

shapq이 다를경우 어떤 axis 는 동작을 안하기 때문에 각 배열의 shape을 잘 확인해야 합니다. 

 

a, b의 shape을 먼저 확인해 봅시다.

a는 (3,4) b는 (3,2)로 column 의 shape이 다릅니다. 

 

예시 코드에서는 axis =1 즉 column 방향으로 연산을 실행했는데요. 아무 문제없이 작동합니다.

 

하지만 axis = 0 방향으로 했을때는 오류가 납니다.  왜냐하면 아래와같이 빈곳(?)이 생기기 때문이죠.

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - concatenate

 

이번엔 3차원 텐서끼리의 연산(shape이 다를 경우)을 보겠습니다. 

3차원이기 때문에 axis는 3개(채널방향, row방향, column 방향)가 있겠죠 .

 

아래와 같은 (4,4,5) (5,4,5) 2개 텐서를 연산을 하려고 합니다.

shape 형태를 보니 채널 의shape만 다르고 나머지는 다 같은 형태입니다. 

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - concatenate

 

이때 가능한 연산방향은 아래 그림과 같은 채널방향입니다. 

 

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - concatenate

코드를 통해 확인해 보겠습니다. 

import numpy as np

a = np.random.randint(0, 10, (4, 4, 5))

b = np.random.randint(0, 10, (5, 4, 5)) 

concat0 = np.concatenate([a, b], axis = 0)
print(f"concat0.shape: {concat0.shape}")

output :

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - concatenate

채널 방향으로 연산(axis = 0)을 하다보니 채널의 shape이 합쳐져서 9가 된것을 볼수가있네요

 

혹시 이해가 안되시는 분들을 위해 row 방향(axis = 1)으로 하면 어떻게 될까요? 그림은 아래와 같습니다. 

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - concatenate

채널 갯수가 다르다 보니 파란색 행렬 뒤가 좀 휑한게(?) 보이시죠? 짝이 맞지 않습니다.

 

아래는 axis =1로 계산한 코드입니다.

import numpy as np

a = np.random.randint(0, 10, (3, 4, 5))

b = np.random.randint(0, 10, (5, 4, 5)) 

concat0 = np.concatenate([a, b], axis = 1) # row방향으로 했을때는 그림을 보면 파란색이 초록색 에 비해 차원갯수가 하나가 적어서 row #방향으로 했을때 연산이 실패한다.
print(f"concat0.shape: {concat0.shape}")

output :

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - concatenate

all the input array dimensions for the concatenation axis must match exatly... 라는 ValueError가 발생합니다.

 

그럼 확인사살을 위해 제일 안쪽차원인 column 방향(-1 or 2) 어떨까요?

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - concatenate

보시는것처럼 파란색 채널수가 부족하니 짝이 맞지 않습니다. 

mport numpy as np

a = np.random.randint(0, 10, (3, 4, 5))

b = np.random.randint(0, 10, (5, 4, 5)) 

concat0 = np.concatenate([a, b], axis = -1)
print(f"concat0.shape: {concat0.shape}")

output :

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - concatenate

이 또한 같은 ValueError가 발생합니다. 

 

앞에서는 채널이 다를 경우 어떤 axis 방향의 연산이 가능한지 알아보았는데요.

이번에는 row만 다른 경우를 알아보겠습니다.  

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - concatenate

정답부터 말하자면 row가 다른 텐서에서는 row 방향 즉 axis = 1 연산만 가능합니다. 

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - concatenate

import numpy as np

a = np.random.randint(0, 10, (4, 4, 5))

b = np.random.randint(0, 10, (4, 5, 5)) 

concat0 = np.concatenate([a, b], axis = 1)
print(f"concat0.shape: {concat0.shape}")

output :

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - concatenate

 

row만 다른경우는 axis = 0, axis = 2에서는 왜 안되는지 설명하진 않겠습니다. 

앞서 배운대로 머리에 그림을 떠올려보시면 충분히 아실 수 있을 겁니다.

 

 

이번에는 마지막으로 column shape만 다른 경우입니다.

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - concatenate

정답부터 말하면 column 방향 즉 axis = -1 or 2 만 가능합니다. 

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - concatenate

import numpy as np

a = np.random.randint(0, 10, (4, 4, 5))

b = np.random.randint(0, 10, (4, 4, 6)) 

concat0 = np.concatenate([a, b], axis = -1)
print(f"concat0.shape: {concat0.shape}")

output :

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - concatenate

차원이 더커지게 되면 헷갈릴 수 있지만 여기서 우리는 한가지 규칙을 알 수 있습니다.

(4,4,5) (4,4,6) column만 다를때 -> column방향 axis = 2 or -1
(4,4,5) (5,4,5) 채널만 다를때 -> 채널방향 axis = 0
(4,4,5) (4,5,5) row만 다를때 -> row 방향 aixs = 1

 

np.dstack (demension stack)

이어서 배워볼 api는 demension stack 이라 불리는 dstack 입니다.

이름에서 추론할수있듯이 차원방향 즉 채널 방향으로 합치는 것입니다. 

 

이 api 특이한점은 2차원같이 행 과 열밖에 없는 shape의 배열들끼리 합칠때도 

채널을 기여코(?) 만들어 채널 연산을 수행한다는 것인데요..

 

바로 코드를 통해 작동 원리를 알아보겠습니다. 

import numpy as np

R = np.random.randint(0, 10, (100, 200))
G = np.random.randint(0, 10, size=R.shape)
B = np.random.randint(0, 10, size=R.shape)

image = np.dstack([R, G, B])

print(image.shape)

(100,200)의 shape을 가진 R, G, B  행렬을 만듭니다. 

이전에 배웠던 방식처럼 dstack에도 인자로 리스트와 각각의 행렬들을 집어넣는데요 어떤 결과가 나올까요?

 

output :

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - np.dstack (demension stack)

분명 2차원끼리 합쳤는데 차원이 하나가 추가된것을 알수가 있습니다. 

차원이 하나가 추가되긴했는데 (3, 100, 200) 이 아니라 (100, 200, 3) 안쪽 차원 방향으로 추가가 되었네요..

앞서 말씀드린대로 차원끼리 더한걸 알 수있습니다. 

 

이번엔 3차원 배열들 끼리의 연산입니다. 

 

import numpy as np

a = np.random.randint(0, 10, (100, 200, 3))
b = np.random.randint(0, 10, size=a.shape)
c = np.random.randint(0, 10, size=a.shape)

d = np.dstack([a, b, c])
print(d.shape)

 

output : 

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - np.dstack (demension stack)

3차원에는 차원 방향으로 연산을할때 굳이 새로운 차원을 만들어 줄 필요가 없으니 차원 변화 없이 제일 안쪽 차원끼리 더하는 것을 알 수 있습니다. 

 

마지막으로 그럼 1차원 벡터들끼리는 여떻게 연산이 될까요?

import numpy as np

a = np.random.randint(0, 10, (100,))
b = np.random.randint(0, 10, size=R.shape)
c = np.random.randint(0, 10, size=R.shape)

d = np.dstack([a, b, c])
print(d.shape)

1차원은 차원 방향으로 더하기에는 애초에 row 방향 밖에 없는데 어떻게 계산이 될까요?

output : 

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - np.dstack (demension stack)

제일 바깥쪽 차원에 1을 만들어 size를 유지한다음 기어코(?) 제일 안쪽 차원 방향으로 합하는 것을 알 수가 있습니다. 

 

stack

stack은 dstack과 비슷한것같으면 서도 다른데요. 더 general 하게 사용할수있는 api라고 보실 수 있습니다. 

우선 코드를 통해 어떻게 작동하는지 알아볼게요

 

import numpy as np

a = np.random.randint(0, 10, (100, 200))
b = np.random.randint(0, 10, size=a.shape)
c = np.random.randint(0, 10, size=a.shape)

d = np.stack([a, b, c])
print(d.shape)

output : 

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - stack

차원이 새롭게 생기는데 여기선 제일 바깥쪽 차원이 생긴것을 알 수있습니다. 

뭔가 dstack 은 제일 안쪽 차원을 더했다면, stack은 제일 바깥차원끼리 더하는건가? 라고 의문이 들기 시작할겁니다. 

이번엔 이어서 3차원 배열의 연산입니다.

a = np.random.randint(0, 10, (100, 200, 300))
b = np.random.randint(0, 10, size=a.shape)
c = np.random.randint(0, 10, size=a.shape)

d = np.stack([a, b, c])
print(d.shape)

output : 

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - stack

dstack과 같은 원리라면 (300, 200,300) 이 되어야 하는데 또 차원이 추가되네요.

여기서 알아야할것은 stack 은 무조건 한차원을 추가한다는 겁니다. 

 

이때 중요한 것은 axis 를 통해 어떤 부분에 차원을 더할건지 커스터마이징이 가능하다는것인데요.

디폴트값으로 axis = 0 입니다. 그래서 앞선 예에서 가장 바깥쪽 차원방향으로 차원이 더해진 것이구요.

 

이번엔 axis를 바꿔가며 어떠한 연산을 하는지 자세히 알아보겠습니다. 

 

1. axis = 0

a = np.random.randint(0, 10, (100, 200, 300))
b = np.random.randint(0, 10, size=a.shape)
c = np.random.randint(0, 10, size=a.shape)

d = np.stack([a, b, c], axis = 0)
print(d.shape)

output : 

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - stack

앞서 디폴트로 지정했을때와 같은 값이죠?

제일 바깥 쪽 차원에 새로운 차원값이 추가되었습니다. 

 

2. axis = 1

a = np.random.randint(0, 10, (100, 200, 300))
b = np.random.randint(0, 10, size=a.shape)
c = np.random.randint(0, 10, size=a.shape)

d = np.stack([a, b, c], axis = 1)
print(d.shape)

output : 

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - stack

axis =1 로 하자 그다음 차원에서 새로운 차원을 추가하네요

 

3. axis = 2

a = np.random.randint(0, 10, (100, 200, 300))
b = np.random.randint(0, 10, size=a.shape)
c = np.random.randint(0, 10, size=a.shape)

d = np.stack([a, b, c], axis = 2)
print(d.shape)

output : 

[넘파이 기초]  vstack | hstack | concatenate | dstack | stack 마스터 - undefined - stack

 

이제 어느정도 잠이 잡히셨죠?

 

 

정리

일반적으로 hstack, vstack , dstack은 2차원 행렬에 자주 사용되고,

concatenate, stack은 더 고차원에서 자주 사용됩니다.

 

 

 

이 글과 읽으면 좋은글

  • 트위터 공유하기
  • 페이스북 공유하기
  • 카카오톡 공유하기
이 컨텐츠가 마음에 드셨다면 커피 한잔(후원) ☕

댓글

꼬예님의
글이 좋았다면 응원을 보내주세요!