1️⃣ Iterating( ndarray 반복 )
c = np.arange(24).reshape(2, 3, 4) # A 3D array (composed of two 3x4 matrices)
c
# [[[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]],
# [[12, 13, 14, 15],
# [16, 17, 18, 19],
# [20, 21, 22, 23]]]
# 다차원 배열의 반복
for m in c:
print("Item:")
print(m) # 3x4 배열 2개 출력
# Item:
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
# Item:
# [[12 13 14 15]
# [16 17 18 19]
# [20 21 22 23]]
# 인덱스 반복
for i in range(len(c)): # Note that len(c) == c.shape[0]
print("Item:")
print(c[i])
# Item:
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
# Item:
# [[12 13 14 15]
# [16 17 18 19]
# [20 21 22 23]]
# 모든 요소 순회
for i in c.flat: # c.flat: 3차원 배열을 1차원 배열로 변환
print(i) # 모든 요소 0~23 출력
# Item: 0
# Item: 1
# Item: 2
# Item: .
# Item: .
# Item: .
# Item: 23
- for m in c: 의 경우, 배열 c에 대해서 가장 바깥쪽 차원(3차원일 경우 z, 2차원일 경우 y)을 기준으로 m[0], ... 이 반환됨.
- 위의 예시는 3차원이기 때문에 z축, 즉 axis 0 을 기준으로 쪼개서 반환됨. - for i in range(len(c)): 의 경우, len(c) 값 2는, c.shape[0] 과 같기 때문에 for i in range(c.shape[0]): 과 동일.
- c.shape = (2, 3, 4) 이기 때문에 c.shape[0] = 2, c.shape[1] = 3, c.shape[2] = 4 임.
- 따라서, 위의 예시는 z축 방향으로 순회하여 반환하는 것
- 인덱스 반복 방식으로 y축 방향으로 짜르게 위해서 이런 방식을 사용.
for i in range(c.shape[1]):
print("Item:")
print(c[:, i, :])
# Item:
# [[ 0 1 2 3]
# [12 13 14 15]]
# Item:
# [[ 4 5 6 7]
# [16 17 18 19]]
# Item:
# [[ 8 9 10 11]
# [20 21 22 23]]
2️⃣ 배열 쌓기 (Stacking Arrays)
q1 = np.full((3, 4), 1.0)
q2 = np.full((4, 4), 2.0)
q3 = np.full((3, 4), 3.0)
# q1 (3, 4)
# [[1. 1. 1. 1.]
# [1. 1. 1. 1.]
# [1. 1. 1. 1.]]
# q2 (4, 4)
# [[2. 2. 2. 2.]
# [2. 2. 2. 2.]
# [2. 2. 2. 2.]
# [2. 2. 2. 2.]]
# q3 (3, 4)
# [[3. 3. 3. 3.]
# [3. 3. 3. 3.]
# [3. 3. 3. 3.]]
vstack
q4 = np.vstack((q1, q2, q3))
print(q4.shape)
print(q4)
# (10, 4)
# [[1. 1. 1. 1.]
# [1. 1. 1. 1.]
# [1. 1. 1. 1.]
# [2. 2. 2. 2.]
# [2. 2. 2. 2.]
# [2. 2. 2. 2.]
# [2. 2. 2. 2.]
# [3. 3. 3. 3.]
# [3. 3. 3. 3.]
# [3. 3. 3. 3.]]
- vstack은 매개변수로 들어온 배열 q1, q2, q3 를 y축 새로 방향으로 합침.(2차원 배열에 대해서만 가능)
- 때문에 합쳐지는 배열들의 x축의 길이가 모두 같아야 함. (q1, q2, q3 는 x축의 길이가 4로 모두 같음)
- x축의 길이가 다른 배열을 vstack하려고 하면 오류가 발생
- vstack은 copy 방식이기 때문에, q1, q2, q3와 메모리를 공유하지 않음(q1, q2, q3가 바뀌어도 q4는 반영 x)
hstack
q5 = np.hstack((q1, q3))
print(q5.shape)
print(q5)
# (3, 8)
# [[1. 1. 1. 1. 3. 3. 3. 3.]
# [1. 1. 1. 1. 3. 3. 3. 3.]
# [1. 1. 1. 1. 3. 3. 3. 3.]]
- hstack은 매개변수로 들어온 배열 q1, q3 를 x축 새로 방향으로 합침. (2차원 배열에 대해서만 가능)
- 때문에 합쳐지는 배열들의 y축의 길이가 모두 같아야 함. (q1, q3 는 y축의 길이가 3으로 모두 같음)
- y축의 길이가 다른 배열을 hstack하려고 하면 오류가 발생
- hstack은 copy 방식이기 때문에, q1, q3와 메모리를 공유하지 않음(q1, q3가 바뀌어도 q5는 반영 x)
concatenate
q7 = np.concatenate((q1, q2, q3), axis=0) # np.vstack(q1, q2, q3)과 동일
print(q7.shape)
print(q7)
# (10, 4)
# [[1. 1. 1. 1.]
# [1. 1. 1. 1.]
# [1. 1. 1. 1.]
# [2. 2. 2. 2.]
# [2. 2. 2. 2.]
# [2. 2. 2. 2.]
# [2. 2. 2. 2.]
# [3. 3. 3. 3.]
# [3. 3. 3. 3.]
# [3. 3. 3. 3.]]
# 실습 문제
# concatenate 함수를 사용해서 ndarray q1과 q3을 수평 방향으로 붙이기
q_con = np.concatenate((q1, q3), axis=1) # np.hstack(q1, q3)과 동일
print(q_con.shape)
print(q_con)
# (3, 8)
# [[1. 1. 1. 1. 3. 3. 3. 3.]
# [1. 1. 1. 1. 3. 3. 3. 3.]
# [1. 1. 1. 1. 3. 3. 3. 3.]]
- concatenate는 매개변수로 들어온 배열 q1, ,q2, q3 을 주어진 축에 합침. (모든 차원에 대해서 가능)
- q1, q2, q3이 2차원 배열이기 때문에, axis=0은 y축임. -> (np.vstack(q1, q2, q3) 와 기능이 같음)
- 때문에 합쳐지는 배열들의 조건이 vstack이나 hstack의 조건이 만족해야함
- 조건이 맞지 않으면 오류 발생
- concatenate는 vstack과 hstack과 같은 기능을 하기 때문에, 메모리 공유 x
stack
q8 = np.stack((q1, q3)) # 새로운 축 z를 만들면서 q1, q3를 합치면서 q8를 생성
print(q8.shape)
print(q8)
# (2, 3, 4)
# [[[1. 1. 1. 1.]
# [1. 1. 1. 1.]
# [1. 1. 1. 1.]]
#
# [[3. 3. 3. 3.]
# [3. 3. 3. 3.]
# [3. 3. 3. 3.]]]
- q1, q3이 2차원 배열이기 때문에 stack 시에 z축을 만들면서 3차원 배열 q8을 생성
- z축의 0번째 인덱스에 q1, 1번째 인덱스에 q3이 들어가 합쳐짐
- 합쳐지는 배열 q1, q3의 shape이 완전히 일치해야지만 stack 가능
- 배열의 shape가 다를 경우 오류 발생
- stack은 copy 방식이기 때문에, q1, q3와 메모리를 공유하지 않음(q1, q3가 바뀌어도 q8는 반영 x)
3️⃣ 배열 분할( Splitting arrays )
r = np.arange(24).reshape(2, 3, 4)
r
# [[[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]],
# [[12, 13, 14, 15],
# [16, 17, 18, 19],
# [20, 21, 22, 23]]]
vsplit & hsplit
r1, r2, r3 = np.vsplit(r, 3)
r4, r5 = np.hsplit(r, 2)
# r1
# [[0, 1, 2, 3],
# [4, 5, 6, 7]]
# r2
# [[ 8, 9, 10, 11],
# [12, 13, 14, 15]]
# r3
# [[16, 17, 18, 19],
# [20, 21, 22, 23]]
# r4
# [[ 0, 1],
# [ 4, 5],
# [ 8, 9],
# [12, 13],
# [16, 17],
# [20, 21]]
# r5
# [[ 2, 3],
# [ 6, 7],
# [10, 11],
# [14, 15],
# [18, 19],
# [22, 23]]
- vsplit과 hsplit은 vstack과 hstack과 반대로 하나의 배열을 쪼개는 것
- vsplit은 y축 방향으로 매개변수로 주어진 크기만큼으로 n등분 쪼개는것!
- r1, r2, r3 = np.vsplit(r, 3) 이면 r을 y축 방향으로 3등분해서 r1, r2, r3에 저장.
- hsplit은 x축 방향으로 매개변수로 주어진 크기만큼으로 n등분 쪼개는것!
- r4, r5 = np.hsplit(r, 2) 이면 r을 x축 방향으로23등분해서 r3, r4에 저장.
4️⃣ 전치 ( Transposing arrays )
t = np.arange(24).reshape(4, 2, 3)
t
# [[[ 0, 1, 2],
# [ 3, 4, 5]],
#
# [[ 6, 7, 8],
# [ 9, 10, 11]],
#
# [[12, 13, 14],
# [15, 16, 17]],
#
# [[18, 19, 20],
# [21, 22, 23]]]
transpose & swapaxes
# t는 (4, 2, 3) -> (z, y, x) 이기 때문에 z(0) = 4, y(1) = 2, x(2) =3 임
# transpose는 (0, 1, 2) 의 배열을 매개변수로 넘겨 받은 방향으로 변환
t1 = t.transpose((1, 2, 0)) # (0, 1, 2) -> (1, 2, 0) shape (2, 3, 4) 가 반환
# t1 (2, 3, 4)
# [[[ 0 6 12 18]
# [ 1 7 13 19]
# [ 2 8 14 20]]
#
# [[ 3 9 15 21]
# [ 4 10 16 22]
# [ 5 11 17 23]]]
t2 = t.transpose() # 기본: (0, 1, 2) -> (2, 1, 0) shape (3, 2, 4) 반환
# t2 (3, 2, 4)
# [[[ 0 6 12 18]
# [ 3 9 15 21]]
#
# [[ 1 7 13 19]
# [ 4 10 16 22]]
#
# [[ 2 8 14 20]
# [ 5 11 17 23]]]
t3 = t.swapaxes(0, 1) # (0, 1, 2) -> (1, 0, 2) shape (2, 4, 3) 반환
# t3 (2, 4, 3)
# [[[ 0 1 2]
# [ 6 7 8]
# [12 13 14]
# [18 19 20]]
#
# [[ 3 4 5]
# [ 9 10 11]
# [15 16 17]
# [21 22 23]]]
# 실습 문제
# ndarray t에 대해서 기존 y-axis가 x-axis로, z-axis가 y-axis로, x-axis가 z-axis로 transpose
t4 = t.transepose(2, 0 ,1)
# shape (3, 4, 2) 반환
- 3차원 배열 (z, y, x) 의 경우 axis 0 = z, axis 1 = y, axis 2 = x 임.
- (0, 1, 2) 인 3차원 배열을 바꾸는 것을 transpose 함수.
- t1. = t.transpose(1, 2, 0) 의 경우, (0, 1, 2) -> (1, 2, 0) 으로 변환.(즉, (4, 2, 3) -> (2, 3, 4) 으로 shape이 바뀜)
- 변환된 배열의 요소가 어떻게 들어가는지 헷갈리면, 반환되는 shape을 적어놓고, axis = 1의 축을 기준으로 가로로 보는 걸 추천!!
- t2 = t.transpose() 는 t2 = t.transpose(2, 1, 0) 과 동일.
- 즉, 이전 배열을 완전히 반전하는 것!
- t3 = t.swapaxes(0, 1) 의 경우, axis 0과 axis 1의 위치를 바꾸는 것.
- 즉, t3 = t.swapaxes(0, 1) 는 t3 = t.transpose(1, 0, 2)
**transepose와 swapaxes는 t와 t1, t2, t3, t4가 메모리를 공유함.(즉, t1, t2, t3, t4 가 바뀌면 t도 같이 바뀜)**
5️⃣ 1차원 배열 전치( m.T )
m1 = np.arange(10).reshape(2,5)
m1
# shape (2, 5)
# [[0, 1, 2, 3, 4],
# [5, 6, 7, 8, 9]]
m1.T # m1.transpose() 와 동일
# shape (5, 2)
# [[0, 5],
# [1, 6],
# [2, 7],
# [3, 8],
# [4, 9]]
m2 = np.arange(5)
m2
# shape (5,)
# [0, 1, 2, 3, 4]
m2.T
# shape(5,)
# [0, 1, 2, 3, 4] (1차원 배열의 경우, 변화 없음)
m2r = m2.reshape(1,5)
m2r
# shape(5,1)
# [[0],
# [1],
# [2],
# [3],
# [4]]
- m.T 의 경우, 대칭으로 변환 (모든 차원에 대해서 가능)
- m.transpose() 와 동일함.
- 1차원 배열에 대해서는 T는 변화가 없음.
'AI(ML & DL)' 카테고리의 다른 글
| [기계학습] Python Pandas 란 ?? ( 1 ) (1) | 2025.03.31 |
|---|---|
| [기계학습] Python NumPy 란 ?? ( 4 ) (0) | 2025.03.31 |
| [기계학습] Python NumPy란?? ( 2 ) (0) | 2025.03.24 |
| [기계학습] Python NumPy란?? ( 1 ) (0) | 2025.03.21 |
| [기계학습] ML(Machine Learning)의 주요 과제(데이터, 알고리즘 문제) (1) | 2025.03.17 |