이번 포스팅에서는 넘파이 배열의 형태를 조작하는 reshape, resize 메서드에 대해 알아보도록 하겠습니다.
import numpy as np
reshape 메서드
- np.reshape(a, newshape, ...)
- ndarray.reshape(shape, ...)
arr1 = np.arange(6)
print(arr1)
# [0 1 2 3 4 5]
print(arr1.shape) # (6, )
print(arr1.size) # 6
arr2 = np.reshape(arr1, (2, 4))
# ValueError: cannot reshape array of size 6 into shape (2,4)
reshape 메서드는 기존 배열의 형태를 변환합니다.
단, 변환 전과 후의 size 속성값이 일치해야 합니다.
이 조건을 만족하지 않으면 ValueError가 발생합니다.
arr1 = np.arange(18)
arr2 = np.reshape(arr1, (2, 3, 3))
print(arr1)
# [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17]
print(arr1.size)
# 18
print(arr2)
# [[[ 0 1 2]
# [ 3 4 5]
# [ 6 7 8]]
# [[ 9 10 11]
# [12 13 14]
# [15 16 17]]]
print(arr2.size)
# 18
아래 예제코드는 기존 배열을 3차원으로 변환합니다.
a = np.random.randint(0, 15, (15, ))
print(a.reshape((3, 5)).mean(axis=0).max())
print(np.max(np.mean(np.reshape(a, (3, 5)), axis=0)))
np.reshape와 ndarray.reshape 메서드는 기능상 차이가 없습니다.
하지만 코드 가독성 측면에서 차이가 있습니다.
후자는 코드를 앞에서부터 뒤로 자연스럽게 읽을 수 있지만 전자의 경우에는 안에서 밖으로 읽어야 하기 때문에 가독성이 떨어지는 문제가 있습니다.
a = np.random.randint(0, 10, (2, 2))
print(a)
# [[0 0]
# [6 8]]
row_vec = a.reshape(1, -1)
print(row_vec.shape) # (1, 4)
print(row_vec)
# [[0 0 6 8]]
col_vec = a.reshape(-1, 1)
print(col_vec.shape) # (4, 1)
print(col_vec)
# [[0]
# [0]
# [6]
# [8]]
reshape 메서드를 사용할 때 -1을 자주 사용합니다.
-1은 shape의 나머지 부분을 자동으로 계산한다는 의미입니다.
주로 행벡터와 열벡터를 생성할 때 사용합니다.
resize 메서드
- np.resize(a, new_shape, ...)
- ndarray.resize(new_shape, ...)
arr1 = np.arange(6)
print(arr1)
# [0 1 2 3 4 5]
arr2 = np.resize(arr1, (2, 3))
print(arr2)
# [[0 1 2]
# [3 4 5]]
resize 메서드의 결과는 reshape 메서드의 결과와 동일해보입니다.
arr1 = np.arange(6)
print(arr1)
# [0 1 2 3 4 5]
arr2 = np.resize(arr1, (10, ))
print(arr2)
# [0 1 2 3 4 5 0 1 2 3]
arr3 = np.reshape(arr1, (10, ))
# ValueError: cannot reshape array of size 6 into shape (10,)
하지만 resize 메서드는 변환 전후 배열의 size 속성값이 다르더라도 에러를 발생시키지 않습니다.
아래 예제코드에서 reshape, resize 메서드의 차이를 확인할 수 있습니다.
resize 메서드를 사용해서 배열을 변환한 결과 size 속성값에 차이가 있다면 부족한 부분은 기존 배열의 원소를 반복함으로써 채웁니다.
arr1 = np.arange(9)
print(arr1)
# [0 1 2 3 4 5 6 7 8]
arr2 = arr1.resize((2, 2))
print(arr1)
# [[0 1]
# [2 3]]
print(arr2)
# None
참고로 ndarray.resize 메서드는 np.resize 메서드와는 달리 기존 배열을 직접(in-place) 변환합니다.
flatten, ravel
m = np.arange(9)
print(m)
# [0 1 2 3 4 5 6 7 8]
n = m.reshape((3, 3))
print(n)
# [[0 1 2]
# [3 4 5]
# [6 7 8]]
p = n.flatten()
print(p)
# [0 1 2 3 4 5 6 7 8]
두 메서드는 n차원 배열을 1차원 배열로 변환(평탄화)합니다.
m = np.arange(9)
print(m)
# [0 1 2 3 4 5 6 7 8]
n = m.reshape((3, 3))
print(n)
# [[0 1 2]
# [3 4 5]
# [6 7 8]]
p = n.ravel()
print(p)
# [0 1 2 3 4 5 6 7 8]
ravel 메서드도 n차원 배열을 1차원 배열로 평탄화합니다.
마치며
이상으로 넘파이 배열의 형태를 조작하는 reshape, resize 메서드에 대한 정리를 마치도록 하겠습니다.
두 메서드는 배열을 반환하는 방식에 차이가 있다는 점을 명심해야겠습니다.
다음 포스팅에서는 넘파이 배열의 원소별 연산(Element-wise operation)에 대해 알아보도록 하겠습니다.
넘파이 배열의 원소별 연산 이해하기(Element-wise operation)
이번 포스팅에서는 넘파이 배열의 연산 방식에 대해 알아보도록 하겠습니다. Element-wise 연산? 기본적으로 넘파이 배열은 모두 원소별 연산을 수행합니다. 원소별로 연산한다는 것의 의미는 각
parix-data.tistory.com
'파이썬・ML > numpy' 카테고리의 다른 글
넘파이 브로드캐스팅(broadcasting) 이해하기 (0) | 2023.07.27 |
---|---|
넘파이 배열의 원소별 연산 이해하기(Element-wise operation) (0) | 2023.07.27 |
넘파이 배열의 생성법과 기본 속성 이해하기 (0) | 2023.07.27 |
넘파이 배열 shape 속성에 대한 이해 (0) | 2023.07.27 |
넘파이 np.repeat(), np.tile() 배열 반복하기 (0) | 2023.06.16 |