[NumPy] 07. ndarray 차원 변경, concatenation, stack
Updated:
ndarray의 차원을 변경하거나 합칠 때 shape을 먼저 생각하면 계산하기 편하다.
import numpy as np
7.1. ndarray ndims 변경
reshape을 활용한 차원 변경
reshape을 그대로 이용하는 것이다. 단, 변경된 shape이 원래 size를 수용할 수 있어야한다.
- np.reshape(a,newshape), a.reshape(newshape): reshape으로 ndims를 ‘증가/감소’할 수 있다. / reshape시 변경된 shape이 원래 size를 수용할 수 있어야한다.
a = np.arange(12)
print(f"a.shape: {a.shape}")
b = np.reshape(a,(3,4))
print(f"b.shape: {b.shape}")
c = np.reshape(b, (-1,))
print(f"c.shape: {c.shape}")
a.shape: (12,)
b.shape: (3, 4)
c.shape: (12,)
a = np.arange(12).reshape((3,4))
print(f"a.shape: {a.shape}")
b = np.reshape(a,(1,*a.shape))
print(f"b.shape: {b.shape}")
a.shape: (3, 4)
b.shape: (1, 3, 4)
slicing을 활용한 ndims 추가
맨 앞, 맨 뒤에만 추가할 수 있다.
- np.newaxis: 새로운 axis를 추가하기위해 사용되는 변수, None 값을 지닌다.
- a[np.newaxis, …], a[… ,np.newaxis] : slicing을 이용해 a의 ndims를 1개 더 증가시킬 수 있다.
print(np.newaxis)
a = np.arange(12)
print(f"a.shape: {a.shape}")
b = a[np.newaxis,...]
print(f"b.shape: {b.shape}")
c = a[...,np.newaxis,np.newaxis]
print(f"c.shape: {c.shape}")
d = a[np.newaxis, ... , np.newaxis]
print(f"d.shape: {d.shape}")
None
a.shape: (12,)
b.shape: (1, 12)
c.shape: (12, 1, 1)
d.shape: (1, 12, 1)
np.expand_dims()를 활용한 ndims 추가
- np.expand_dims(a,axis=(n0,n1,…)): axis parameter를 이용하여 shape에 원하는 위치의 axis를 추가할 수 있다. / axis parameter에 원하는 위치를 튜플로 묶으면 동시에 추가할 수 있다.
a = np.arange(12)
print(f"a.shape: {a.shape}")
b = np.expand_dims(a,axis=0)
print(f"b.shape: {b.shape}")
c = np.expand_dims(a,axis=1)
print(f"c.shape: {c.shape}")
d = np.expand_dims(a,axis=(0,2))
print(f"d.shape: {d.shape}")
a.shape: (12,)
b.shape: (1, 12)
c.shape: (12, 1)
d.shape: (1, 12, 1)
np.squeeze()를 활용한 차원 감소
- np.squeeze(a), a.squeeze(): shape에서 axis가 1인 곳을 모두 없애고 나머지 shape만 남겨둔다.
- np.squeeze(a,axis=()): parameter에 axis를 추가하면 원하는 위치에 있는 값이 1인 axis를 없앨 수 있다. (그 위치의 axis값이 1이 아니면 안된다.)
a = np.arange(20).reshape((1,1,2,1,5,2))
print(f"a.shape: {a.shape}")
b = np.squeeze(a)
print(f"b.shape: {b.shape}")
c = np.squeeze(a,axis=(0,1))
print(f"c.shape: {c.shape")
File "<ipython-input-6-70a0d6ece571>", line 8
print(f"c.shape: {c.shape")
^
SyntaxError: f-string: expecting '}'
7.2. axis swap, move, transpose
swap
- np.swapaxes(a,axis1,axis2): axis1과 axis2를 swap한다.
a = np.random.randint(0,5,(1,3,4))
print(f"a.shape: {a.shape}")
b = np.swapaxes(a,0,1)
print(f"b.shape: {b.shape}")
c = np.swapaxes(a,0,-1)
print(f"c.shape: {c.shape}")
a.shape: (1, 3, 4)
b.shape: (3, 1, 4)
c.shape: (4, 3, 1)
move
- np.moveaxis(a,source,destination): source 위치의 axis를 destination 위치로 이동시킨다.
a = np.random.randint(0,5,(1,3,4,5))
print(f"a.shape: {a.shape}")
b = np.moveaxis(a,0,1)
print(f"b.shape: {b.shape}")
c = np.moveaxis(a,1,-1)
print(f"c.shape: {c.shape}")
a.shape: (1, 3, 4, 5)
b.shape: (3, 1, 4, 5)
c.shape: (1, 4, 5, 3)
transpose
- np.transpose(a), a.transpose(), a.T : 행렬의 transpose와 같은 역할을 한다. / axis 순서를 반대로 뒤바꾼다.
- np.transpose(a, axes=()): 전체 axis를 원하는 위치로 바꾼다. (paramter가 axes에 주의한다.)
a = np.arange(12).reshape((3,4))
print(f"a.shape: {a.shape}")
b = a.transpose()
c = a.T
print(f"b.shape: {b.shape}, c.shape: {c.shape}")
a.shape: (3, 4)
b.shape: (4, 3), c.shape: (4, 3)
a = np.random.randint(1,10,(2,3,4,5))
print(f"a.shape: {a.shape}")
b = np.transpose(a,axes=(2,1,3,0))
print(f"b.shape: {b.shape}")
c = a.transpose()
print(f"c.shape: {c.shape}")
a.shape: (2, 3, 4, 5)
b.shape: (4, 3, 5, 2)
c.shape: (5, 4, 3, 2)
7.3. vstack, hstack, dstack, stack
vstack
axis=0 위치에 ndarray를 합친다.
헹을 하나 더 추가한다고 생각하면 편하다.(vertical-wise)
1차원 ndarray의 경우 shape을 (N,) -> (1,N)으로 바꾼뒤 합친다.
- np.vstack([a,b,c,…]): axis=0 위치를 기준으로 리스트, 튜플로 묶여있는 ndarray를 합친 ndarray를 반환한다.
a = np.random.randint(1,10,(4,))
b = np.random.randint(1,10,(4,))
print(f"a: {a.shape}\n{a}\nb: {b.shape}\n{b}")
print()
c = np.vstack([a,b])
print(f"c: {c.shape}\n {c}")
a: (4,)
[8 6 8 1]
b: (4,)
[5 3 4 5]
c: (2, 4)
[[8 6 8 1]
[5 3 4 5]]
ndarrays = []
for i in range(10):
a = np.random.randint(1,10,(5,))
ndarrays.append(a)
b = np.vstack(ndarrays)
print(f"b.shape: {b.shape}")
b.shape: (10, 5)
hstack
axis=1을 기준으로 ndarray를 합친다.
열을 하나 더 추가한다고 생각하면 편하다.(horizontal-wise)
주의할 점은 합칠 때 dimension을 고려하여 합칠 수 있어야한다. ( e.g. 행렬에 column을 추가할 때)
1차원 ndarray의 경우 shape을 (N,) -> (N,1)으로 바꾼뒤 합친다.
- np.hstack([a,b,c,…]): axis=1 위치를 기준으로 리스트, 튜플로 묶여있는 ndarray를 모두 합친 ndarray를 반환한다.
a = np.random.randint(1,10,(4,))
b = np.random.randint(1,10,(4,))
print(f"a: {a.shape}\n{a}")
print(f"b: {b.shape}\n{b}")
c = np.hstack([a,b])
print(f"c: {c.shape}\n{c}")
a: (4,)
[4 2 9 8]
b: (4,)
[3 1 5 8]
c: (8,)
[4 2 9 8 3 1 5 8]
a = np.random.randint(1,10,(3,4))
b = np.random.randint(1,10,(3,))
print(f"a: {a.shape}\n {a}")
print(f"b: {b.shape}\n {b}")
# b를 a에 그냥 hstack하면 차원이 맞지 않아 Error가 발생한다.
# b를 1차원 증가시켜서 hstack을 해야한다.
b = np.reshape(b,(-1,1))
print(f"b: {b.shape}\n {b}\n")
c = np.hstack([a,b])
print(f"c: {c.shape}\n {c}")
a: (3, 4)
[[6 3 5 7]
[1 7 3 2]
[7 1 7 9]]
b: (3,)
[3 7 5]
b: (3, 1)
[[3]
[7]
[5]]
c: (3, 5)
[[6 3 5 7 3]
[1 7 3 2 7]
[7 1 7 9 5]]
dstack
axis=2를 기준으로 ndarray를 합친다. (depth-wise)
합칠 때 3차원보다 작은 ndarray는 3차원으로 만들고 합친다. 1차원 :(N,) -> (1,N,1), 2차원: (M,N) -> (M,N,1)
- np.vstack([a,b,c,…]): axis=2 위치를 기준으로 리스트, 튜플로 묶여있는 ndarray를 모두 합친 ndarray를 반환한다.
a = np.array([1,2,3])
b = np.array([4,5,6])
print(f"a: {a.shape}\n{a}")
print(f"b: {b.shape}\n{b}\n")
c = np.dstack([a,b])
print(f"c: {c.shape}\n{c}")
a: (3,)
[1 2 3]
b: (3,)
[4 5 6]
c: (1, 3, 2)
[[[1 4]
[2 5]
[3 6]]]
a = np.array([[1],[2],[3]])
b = np.array([[4],[5],[6]])
print(f"a: {a.shape}\n{a}")
print(f"b: {b.shape}\n{b}\n")
c = np.dstack([a,b])
print(f"c: {c.shape}\n{c}")
a: (3, 1)
[[1]
[2]
[3]]
b: (3, 1)
[[4]
[5]
[6]]
c: (3, 1, 2)
[[[1 4]]
[[2 5]]
[[3 6]]]
stack
새로운 axis를 만들고 그 axis를 기준으로 ndarray를 합친다.
- np.vstack([a,b,c,…],axis=n0): axis=n0 위치에 새로운 axis를 추가한 후 그 axis를기준으로 리스트, 튜플로 묶여있는 ndarray를 모두 합친 ndarray를 반환한다.
a = np.random.randint(1,10,(4,5,6))
b = np.random.randint(1,10,(4,5,6))
c = np.random.randint(1,10,(4,5,6))
s1 = np.stack([a,b,c],axis=0)
s2 = np.stack([a,b,c],axis=1)
s3 = np.stack([a,b,c],axis=2)
s4 = np.stack([a,b,c],axis=3)
print(f"s1.shape: {s1.shape}")
print(f"s2.shape: {s2.shape}")
print(f"s3.shape: {s3.shape}")
print(f"s4.shape: {s4.shape}")
s1.shape: (3, 4, 5, 6)
s2.shape: (4, 3, 5, 6)
s3.shape: (4, 5, 3, 6)
s4.shape: (4, 5, 6, 3)
7.4 concatenate
주어진 axis를 기준으로 ndarray를 합친다. 기준이 되는 axis를 제외한 나머지 axis 값은 모두 일치해야한다.
차원이 다른 ndarray를 합치는 경우 차원을 주의해서 합쳐야한다.
- np.concatenate([a,b,c],axis=n0) : 주어진 axis를 기준으로 리스트 또는 튜플로 묶여있는 ndarray를 모두 합친 ndarray를 새로 반환한다.
a = np.random.randint(1,10,(4,))
b = np.random.randint(1,10,(4,))
print(f"a: {a.shape}\n{a}")
print(f"b: {b.shape}\n{b}")
c = np.concatenate([a,b])
print(f"c: {c.shape}\n{c}")
d = np.concatenate([a,b],axis=0)
print(f"d: {d.shape}\n{d}")
a: (4,)
[7 2 7 2]
b: (4,)
[7 9 5 3]
c: (8,)
[7 2 7 2 7 9 5 3]
d: (8,)
[7 2 7 2 7 9 5 3]
a = np.random.randint(1,10,(3,4))
b = np.random.randint(1,10,(1,4))
c = np.random.randint(1,10,(3,1))
print(f"a: {a.shape}\n{a}")
print(f"b: {b.shape}\n{b}")
print(f"c: {c.shape}\n{c}\n")
d = np.concatenate([a,b],axis=0)
print(f"d: {d.shape}\n{d}\n")
e = np.concatenate([a,c],axis=1)
print(f"e: {e.shape}\n{e}")
a: (3, 4)
[[2 7 9 3]
[7 8 5 1]
[7 1 8 1]]
b: (1, 4)
[[8 4 4 3]]
c: (3, 1)
[[1]
[6]
[1]]
d: (4, 4)
[[2 7 9 3]
[7 8 5 1]
[7 1 8 1]
[8 4 4 3]]
e: (3, 5)
[[2 7 9 3 1]
[7 8 5 1 6]
[7 1 8 1 1]]
a = np.random.randint(1,10,(2,3,4))
b = np.random.randint(1,10,(1,3,4))
b1 = np.concatenate([a,b],axis=0)
print(f"b1.shape: {b1.shape}")
c = np.random.randint(1,10,(2,1,4))
c1 = np.concatenate([a,c],axis=1)
print(f"c1.shape: {c1.shape}")
d = np.random.randint(1,10,(2,3,1))
d1 = np.concatenate([a,d],axis=2)
print(f"d1.shape: {d1.shape}")
b1.shape: (3, 3, 4)
c1.shape: (2, 4, 4)
d1.shape: (2, 3, 5)
Leave a comment