numpy API - ndarray 합치기

김상윤·2023년 3월 13일
0

np.hstack과 np.vstack

column 방향으로 / row 방향으로 array를 합칠 것인지 정하는 API이다

import numpy as np
a = np.random.randint(0, 10, (4,)) [4 2 1 0]
b = np.random.randint(0, 10, (4,)) [6 7 2 2]

vstack = np.vstack([a,b])
shape : (2,4)
[[4 2 1 0]
[6 7 2 2]]
hstack = np.hstack([a,b])
shape : (8,)
[4 2 1 0 6 7 2 2]

또 다른 예시

import numpy as np
a = np.random.randint(0, 10, (1,3)) [[0 8 7]]
b = np.random.randint(0, 10, (1,3)) [[9 2 6]] 

vstack = np.vstack((a,b))
shape : (2,3)
[[0 8 7]
 [9 2 6]]
hstack = np.hstack((a,b))
shape : (1,6)
[[0 8 7 9 2 6]]

여기서는 hstack할시 1이라는 차원값이 유지된다는 차이점이 있다.

또다른 예시

import numpy as np
a = np.random.randint(0, 10, (3,1)) [[5][0][8]]
b = np.random.randint(0, 10, (3,1)) [[4][9][7]] 

vstack = np.vstack((a,b))
shape : (6,1)
[[5]
[0]
[8]
[4]
[9]
[7]]
hstack = np.hstack((a,b))
shape : (3,2)
[[5 4]
[0 9]
[8 7]]

조심할 것
(3,4)의 ndarray에 쌓기 위해서는

  • Horizontal : (3, )의 vector shape이면 오류가 난다
    horizontal로 쌓을려면 column vector로 바꿔준 다음 쌓아야 한다.
  • Vertacal : (4, ) shape

Making Datasets

import numpy as np

dataset = np.empty((0,4))

for iter in range(5):
	data_sample = np.random.uniform(0, 5, (1,4))
    dataset = np.vstack((dataset, data_sample))

(4, )의 데이터를 쌓아나갈 예정이라고 생각해보자. 이때 데이터를 쌓을 수 있는 위치를 잡아준다고 생각해주면 된다. dataset에다가 data_sample을 한 줄씩 더해준다.
Making toy dataset

import numpy as np

dataset_tmp = list()
for iter for 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}") (100,4)

np.concatenate & np.dstack, np.stack

np.concatenate

import numpy as np

a = np.random.randint(0, 10, (3, )) [1 9 9]
b = np.random.randint(0, 10, (4, )) [2 6 9 4] 

concat = np.concatenate([a,b]) [1 9 9 2 6 9 4]
concat0 = np.concatenate([a,b],axis = 0) [1 9 9 2 6 9 4]
import numpy as np

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

axis0 = np.concatenate([a,b], axis = 0) (2,3)
axis1 = np.concatenate([a,b], axis = 1) (1,6)
axis_n1 = np.concatenate([a,b], axis=-1) (1,6)

위와 같은 경우 axis 0에 대해 concat한다는 것은 row를 따라 stacking을 한다는 의미와 동일하다. 즉 가독성을 위해서는 np.vstack을 쓰는 것이 더 낫다
axis 1도 마찬가지이다. 가독성을 위해서는 np.hstack이 낫다.

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) (3,6)

(3,4)와 (3,2)는 row의 크기가 같고 column의 크기가 다르다. 그러므로 axis 1에 대해서만 연산이 가능하며 axis 0에 대해서는 오류가 발생한다.

concatenation은 고차원 텐서를 연산할 때 유용하다

import numpy as np

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

b = np.random.randint(0, 10, (10,4,5))
concat0 = np.concatenate([a,b], axis=0)
-> (13,4,5)

나머지 차원이 같을 때 하나의 선택된 차원에 대해서 더할 수 있는 등 vstack, hstack보다 범용적으로 사용할 수 있다.

Making toy dataset

import numpy as np

dataset_tmp = list()
for iter in range(100):
	data_sample = np.random.uniform(0,5,(1,4))
    data_tmp.append(data_sample)
    
concat = np.concatenate(dataset_tmp, axis = 0)
-> (100,4)

for iter in range(100):
	data_sample = np.random.uniform(0,5,(4,1))
    data_tmp.append(data_sample)
    
concat = np.concatenate(dataset_tmp, axis = 1)
-> (4,100)

np.dstack

지금까지는 새로운 차원을 만들면서 합치지는 않았다. 지금까지는 ndarray에 존재하는 차원을 기준으로 stacking을 한다.

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]) -> (100, 200, 3)

dstack은 dimension stack이다. 그리고 제일 안쪽 차원에 새로운 차원이 만들어진다.

import numpy as np

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

image = np.dstack([R,G,B]) -> (100, 200, 9)

이런 결과가 나오므로 concatenation을 사용하는 것이 더 나을 것 같다.

np.stack

import numpy as np

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

np.stack([R,G,B], axis = 0) -> (3, 100, 200,300)
np.stack([R,G,B], axis = 1) -> (100, 3, 200,300)

stack은 axis를 표기하면 원하는 위치에 새로운 차원을 만들면서 stack이 가능하다. vstack, hstack, dstack은 행렬을 다룰 때 사용한다. Concatenation과 stack은 더 고차원을 다룰 때 사용한다.

profile
AI 대학원 지망생

0개의 댓글