NumPy Reshape: Python에서 배열 형상을 변경하는 방법
Updated on
10,000개의 픽셀 값으로 이루어진 평탄한 리스트가 있고 신경망은 100x100 이미지 행렬을 기대합니다. 또는 특성 배열이 1차원인데 열 벡터가 필요해서 scikit-learn이 오류를 발생시키고 있을 수도 있습니다. 이것들은 예외적인 경우가 아닙니다 -- Python에서 수치 데이터를 다루는 모든 사람이 매일 직면하는 장애물입니다. 이를 해결하는 함수가 numpy.reshape()이며, 이를 제대로 이해하면 디버깅 시간을 몇 시간이나 절약할 수 있습니다.
numpy reshape는 무엇을 하나요?
numpy.reshape()는 데이터를 변경하지 않으면서 배열의 형상을 변경합니다. 같은 요소를 가져와서 새로운 차원 세트로 재배열합니다. 12개 요소를 가진 1D 배열은 3x4 행렬, 2x6 행렬, 4x3 행렬, 심지어 2x2x3 3차원 배열이 될 수 있습니다. 유일한 규칙은 전체 요소 수가 동일하게 유지되어야 한다는 것입니다.
import numpy as np
a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
print(a.shape)
# (12,)
b = a.reshape(3, 4)
print(b)
# [[ 1 2 3 4]
# [ 5 6 7 8]
# [ 9 10 11 12]]
print(b.shape)
# (3, 4)원래 배열 a는 원래 형상대로 여전히 존재합니다. reshape된 배열 b는 같은 데이터의 새로운 뷰입니다(뷰와 복사본에 대해서는 나중에 자세히 설명합니다).
기본 구문과 매개변수
NumPy에서 배열을 reshape하는 방법은 두 가지가 있습니다:
# 방법 1: 함수로
np.reshape(array, newshape, order='C')
# 방법 2: 배열 메서드로
array.reshape(newshape, order='C')| 매개변수 | 타입 | 설명 |
|---|---|---|
array | ndarray | reshape할 배열 (np.reshape() 함수 형태에서만 사용) |
newshape | int 또는 int 튜플 | 목표 형상. 하나의 차원을 -1로 설정하면 자동으로 계산됩니다. |
order | 'C', 'F' 또는 'A' | 요소의 읽기/쓰기 순서. 'C' = 행 우선(기본값), 'F' = 열 우선, 'A' = 배열이 Fortran 연속이면 Fortran 순서, 그렇지 않으면 C 순서. |
두 형태 모두 동일한 결과를 생성합니다. 메서드 형태(array.reshape())가 코드에서 더 자연스럽게 읽히기 때문에 더 일반적입니다.
1D에서 2D 배열로 reshape
이것은 가장 빈번한 reshape 작업입니다. 평탄한 배열에서 시작하여 행렬이 필요한 경우입니다.
import numpy as np
# 8개 요소를 가진 1D 배열
data = np.array([10, 20, 30, 40, 50, 60, 70, 80])
# 2행 4열로 reshape
matrix_2x4 = data.reshape(2, 4)
print(matrix_2x4)
# [[10 20 30 40]
# [50 60 70 80]]
# 4행 2열로 reshape
matrix_4x2 = data.reshape(4, 2)
print(matrix_4x2)
# [[10 20]
# [30 40]
# [50 60]
# [70 80]]
# 단일 열 벡터로 reshape (8행, 1열)
column_vector = data.reshape(8, 1)
print(column_vector)
# [[10]
# [20]
# [30]
# [40]
# [50]
# [60]
# [70]
# [80]]
print(column_vector.shape)
# (8, 1)열 벡터 reshape(n, 1)는 특히 중요합니다. 많은 scikit-learn 함수는 단일 특성에 대해서도 2D 입력을 요구합니다. 1D 배열을 전달하면 Expected 2D array, got 1D array instead 오류가 발생합니다. 해결 방법은 .reshape(-1, 1)입니다.
2D에서 3D로 reshape (머신러닝과 딥러닝용)
TensorFlow와 PyTorch 같은 딥러닝 프레임워크는 종종 3D 또는 4D 입력 텐서를 요구합니다. 예를 들어, 그레이스케일 이미지 배치는 (batch_size, height, width) 형상이 필요하고, 컬러 이미지 배치는 (batch_size, height, width, channels)가 필요합니다.
import numpy as np
# 2D 배열의 행으로 저장된 4개의 3x3 그레이스케일 이미지 시뮬레이션
images_2d = np.arange(36).reshape(4, 9)
print(images_2d.shape)
# (4, 9)
# (배치, 높이, 너비)로 reshape
images_3d = images_2d.reshape(4, 3, 3)
print(images_3d.shape)
# (4, 3, 3)
print(images_3d[0])
# [[0 1 2]
# [3 4 5]
# [6 7 8]]3채널(RGB) 컬러 이미지의 경우:
import numpy as np
# 2개의 컬러 이미지, 각각 4x4, 3채널, 평탄하게 저장
flat_data = np.arange(96) # 2 * 4 * 4 * 3 = 96
images = flat_data.reshape(2, 4, 4, 3)
print(images.shape)
# (2, 4, 4, 3)-1 트릭: 하나의 차원을 자동 계산
하나의 차원을 -1로 설정하면, NumPy가 전체 요소 수와 지정한 다른 차원을 기반으로 자동으로 계산합니다. 이것은 reshape의 가장 유용한 기능 중 하나입니다.
import numpy as np
arr = np.arange(12)
# "3행으로 해줘, 열은 계산해줘"
print(arr.reshape(3, -1))
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
# 형상: (3, 4) -- NumPy가 4열을 계산
# "2열로 해줘, 행은 계산해줘"
print(arr.reshape(-1, 2))
# [[ 0 1]
# [ 2 3]
# [ 4 5]
# [ 6 7]
# [ 8 9]
# [10 11]]
# 형상: (6, 2) -- NumPy가 6행을 계산
# 1D로 평탄화
print(arr.reshape(-1))
# [ 0 1 2 3 4 5 6 7 8 9 10 11]
# 형상: (12,)
# 열 벡터
print(arr.reshape(-1, 1).shape)
# (12, 1)-1은 하나의 차원에만 사용할 수 있습니다. 두 개 이상의 차원에 사용하면 계산이 모호해지므로 오류가 발생합니다.
import numpy as np
arr = np.arange(12)
# 이것은 실패합니다:
# arr.reshape(-1, -1)
# ValueError: can only specify one unknown dimensionreshape()와 resize()의 차이: 주요 차이점
두 함수 모두 배열 형상을 변경하지만, 동작 방식이 매우 다릅니다.
| 특징 | reshape() | resize() |
|---|---|---|
| 반환값 | 새 배열 (뷰 또는 복사본) | 배열을 인플레이스로 수정(메서드) 또는 새 배열 반환(함수) |
| 크기 일치 필요 | 예 -- 전체 요소 수가 동일해야 함 | 아니오 -- 0으로 채우거나 잘라냄 |
| 원래 배열 | 변경 없음 | 변경됨 (ndarray.resize() 사용 시) |
| 안전성 | 크기 불일치 시 오류 발생 | 조용히 채우거나 잘라냄 |
| 일반적 용도 | 차원 재배열 | 배열 크기 변경 |
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6])
# reshape: 동일한 전체 요소 수를 유지해야 함
reshaped = arr.reshape(2, 3)
print(reshaped)
# [[1 2 3]
# [4 5 6]]
# np.resize (함수 형태): 새 크기가 더 크면 반복하여 채움
resized = np.resize(arr, (3, 3))
print(resized)
# [[1 2 3]
# [4 5 6]
# [1 2 3]] <-- 처음부터 반복
# np.resize: 새 크기가 더 작으면 잘라냄
resized_small = np.resize(arr, (2, 2))
print(resized_small)
# [[1 2]
# [3 4]]데이터를 변경하지 않고 차원을 재배열하려면 reshape()를 사용하세요. 요소 수를 실제로 변경해야 할 때만 resize()를 사용하세요.
order 매개변수: C vs F vs A
order 매개변수는 원래 배열에서 요소를 어떻게 읽고 새 형상에 배치하는지를 제어합니다. 다른 프로그래밍 언어나 저장 형식의 데이터로 작업할 때 중요합니다.
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6])
# C 순서 (행 우선): 행별로 채움 -- 기본값
c_order = arr.reshape(2, 3, order='C')
print("C 순서:")
print(c_order)
# [[1 2 3]
# [4 5 6]]
# F 순서 (열 우선): 열별로 채움
f_order = arr.reshape(2, 3, order='F')
print("F 순서:")
print(f_order)
# [[1 3 5]
# [2 4 6]]| Order | 이름 | 채우기 방식 | 사용 사례 |
|---|---|---|---|
'C' | C 스타일 / 행 우선 | 행별 (마지막 인덱스가 가장 빠르게 변화) | Python/C/C++ 기본 메모리 레이아웃 |
'F' | Fortran 스타일 / 열 우선 | 열별 (첫 번째 인덱스가 가장 빠르게 변화) | MATLAB, Fortran, R 데이터 |
'A' | 자동 | 배열이 Fortran 연속이면 F, 아니면 C | 기존 메모리 레이아웃 유지 |
대부분의 경우 기본 'C' 순서를 사용합니다. MATLAB이나 Fortran에서 내보낸 데이터를 로드할 때 'F' 순서가 필요합니다. 이러한 환경에서는 행렬이 열별로 저장됩니다.
뷰와 복사본: reshape가 뷰를 반환하는 경우
중요한 세부 사항: reshape()는 가능할 때마다 원래 배열의 뷰를 반환합니다. 뷰는 같은 기본 메모리를 공유합니다. 뷰를 수정하면 원래 배열도 수정되고, 그 반대도 마찬가지입니다.
import numpy as np
original = np.arange(6)
reshaped = original.reshape(2, 3)
# reshape된 뷰를 수정
reshaped[0, 0] = 999
print(original)
# [999 1 2 3 4 5] <-- 원래 배열도 변경됨!NumPy가 뷰를 만들 수 없는 경우(예: 메모리 레이아웃이 새 형상과 호환되지 않는 경우), 대신 복사본을 반환합니다. 명시적으로 복사본을 강제할 수 있습니다:
import numpy as np
original = np.arange(6)
reshaped_copy = original.reshape(2, 3).copy()
reshaped_copy[0, 0] = 999
print(original)
# [0 1 2 3 4 5] <-- 원래 배열은 영향을 받지 않음reshape가 뷰를 반환했는지 복사본을 반환했는지 확인하려면 base 속성을 검사하세요:
import numpy as np
arr = np.arange(6)
view = arr.reshape(2, 3)
copy = arr.reshape(2, 3).copy()
print(view.base is arr) # True -- 뷰입니다
print(copy.base is arr) # False -- 복사본입니다일반적인 오류와 해결 방법
오류: "cannot reshape array of size X into shape Y"
이것은 가장 일반적인 reshape 오류입니다. 전체 요소 수가 목표 형상과 일치하지 않을 때 발생합니다.
import numpy as np
arr = np.arange(10)
# 10 != 3 * 4 = 12 이므로 실패
# arr.reshape(3, 4)
# ValueError: cannot reshape array of size 10 into shape (3,4)해결 방법:
- 계산을 확인하세요. 모든 목표 차원의 곱이
arr.size와 같은지 확인합니다.
import numpy as np
arr = np.arange(10)
print(arr.size) # 10
# 10개 요소에 유효한 형상: (2,5), (5,2), (1,10), (10,1), (10,)
print(arr.reshape(2, 5))
# [[0 1 2 3 4]
# [5 6 7 8 9]]- 배열을 패딩하거나 잘라내세요. 균등하게 나누어지지 않는 형상이 정말로 필요한 경우입니다.
import numpy as np
arr = np.arange(10)
# 12개 요소로 패딩한 후 (3, 4)로 reshape
padded = np.pad(arr, (0, 2), constant_values=0)
print(padded.reshape(3, 4))
# [[0 1 2 3]
# [4 5 6 7]
# [8 9 0 0]]- -1을 사용하여 NumPy가 하나의 차원을 계산하게 하여 수동 계산 오류를 방지하세요.
import numpy as np
arr = np.arange(10)
print(arr.reshape(-1, 2))
# [[0 1]
# [2 3]
# [4 5]
# [6 7]
# [8 9]]오류: "Expected 2D array, got 1D array instead"
이 scikit-learn 오류는 1D 특성 배열을 전달할 때 나타납니다. 해결 방법은 간단합니다:
import numpy as np
features = np.array([1.5, 2.3, 3.1, 4.7, 5.0])
# 열 벡터로 변환
features_2d = features.reshape(-1, 1)
print(features_2d.shape)
# (5, 1)실전 예제
Scikit-Learn용 데이터 준비
scikit-learn은 (n_samples, n_features) 형상의 특성 행렬을 기대합니다. 간단한 선형 회귀를 위해 데이터를 올바르게 reshape하는 방법은 다음과 같습니다:
import numpy as np
# 단일 특성: 주택 크기(평방피트)
sizes = np.array([850, 1200, 1500, 1800, 2100, 2400, 2800])
# sklearn용으로 (n_samples, 1)로 reshape
X = sizes.reshape(-1, 1)
print(X.shape)
# (7, 1)
# 목표 변수(가격)는 이미 1D이며, sklearn이 허용함
y = np.array([150000, 220000, 275000, 320000, 380000, 430000, 510000])
# 이제 X와 y는 sklearn에 사용할 준비가 됨
# from sklearn.linear_model import LinearRegression
# model = LinearRegression().fit(X, y)이미지 데이터 reshape
이미지 데이터셋으로 작업할 때 평탄한 벡터와 공간 차원 사이의 reshape가 자주 필요합니다:
import numpy as np
# 28x28 그레이스케일 이미지를 평탄한 배열로 로드하는 시뮬레이션 (MNIST처럼)
flat_image = np.random.randint(0, 256, size=784)
print(flat_image.shape)
# (784,)
# 2D 이미지로 reshape
image_2d = flat_image.reshape(28, 28)
print(image_2d.shape)
# (28, 28)
# 신경망 입력용으로 100개 이미지 배치를 reshape
batch_flat = np.random.randint(0, 256, size=(100, 784))
batch_images = batch_flat.reshape(100, 28, 28, 1) # 채널 차원 추가
print(batch_images.shape)
# (100, 28, 28, 1)reshape로 전치하기 (그리고 하지 말아야 하는 이유)
흔한 실수는 reshape를 사용하여 행렬을 "전치"하려는 것입니다. reshape는 메모리 순서대로 요소를 재배열하는데, 이는 전치와 다릅니다.
import numpy as np
matrix = np.array([[1, 2, 3],
[4, 5, 6]])
# 잘못됨: reshape(3, 2)는 전치하지 않음
wrong = matrix.reshape(3, 2)
print("reshape(3,2):")
print(wrong)
# [[1 2]
# [3 4]
# [5 6]]
# 올바름: .T 또는 np.transpose() 사용
correct = matrix.T
print("전치:")
print(correct)
# [[1 4]
# [2 5]
# [3 6]]RunCell에서 NumPy Reshape 사용하기
배열을 자주 reshape하고 더 빠른 워크플로우를 원한다면, RunCell (opens in a new tab)은 Jupyter 노트북 내에서 실행되는 AI 에이전트입니다. NumPy, pandas, scikit-learn 코드를 매일 작성하는 데이터 과학자를 위해 만들어졌습니다.
RunCell은 reshape 작업을 여러 가지 방법으로 도울 수 있습니다:
- 즉각적인 형상 디버깅. 형상 불일치 오류가 발생하면 RunCell이 트레이스백을 읽고 올바른 차원과 order 매개변수를 포함한 올바른 reshape 호출을 제안합니다.
- 보일러플레이트 자동 생성. 필요한 것을 자연어로 설명하세요 -- "이 평탄한 배열을 3채널의 32x32 이미지 배치로 reshape해줘" -- RunCell이 코드를 작성합니다.
- 대안 탐색. RunCell은 특정 상황에 따라
reshape,np.expand_dims,np.newaxis,np.squeeze중 어느 것을 사용해야 하는지 보여줄 수 있습니다.
RunCell은 Jupyter 환경에서 직접 작동하므로, 데이터와 코드에 대한 완전한 통제를 유지하면서 필요한 곳에서 정확히 AI 지원 제안을 받을 수 있습니다.
FAQ
numpy reshape(-1)은 무엇을 하나요?
array.reshape(-1)을 호출하면 배열을 1차원으로 평탄화합니다. -1은 NumPy에게 전체 요소 수를 자동으로 계산하라고 지시합니다. array.ravel()이나 array.flatten()과 동등하지만, reshape(-1)은 가능할 때 뷰를 반환하고 flatten()은 항상 복사본을 반환합니다.
numpy reshape는 원래 배열을 변경하나요?
아니요. reshape()는 새로운 배열 객체를 반환합니다. 하지만 반환된 배열이 뷰인 경우(보통 그렇습니다), reshape된 배열을 수정하면 같은 메모리를 공유하기 때문에 원래 배열도 수정됩니다. 이를 방지하려면 결과에 .copy()를 호출하세요.
reshape와 flatten의 차이점은 무엇인가요?
reshape()는 배열을 호환되는 모든 형상으로 변환할 수 있습니다. flatten()은 항상 1D 배열로 변환하고 항상 복사본을 반환합니다. ravel()도 1D로 변환하지만 reshape(-1)과 유사하게 가능할 때 뷰를 반환합니다.
pandas DataFrame을 numpy reshape로 reshape할 수 있나요?
직접적으로는 불가능합니다. 먼저 df.values 또는 df.to_numpy()를 사용하여 기본 NumPy 배열을 추출한 다음 reshape해야 합니다. DataFrame 고유의 reshape 작업에는 pivot(), melt(), stack(), unstack() 같은 pandas 메서드를 사용하세요.
새로운 축을 추가하기 위해 배열을 reshape하려면 어떻게 하나요?
reshape()를 사용할 수 있지만, 단일 차원을 추가할 때는 np.expand_dims()나 np.newaxis가 더 깔끔합니다:
import numpy as np
arr = np.array([1, 2, 3])
# reshape 사용
print(arr.reshape(1, 3).shape) # (1, 3)
print(arr.reshape(3, 1).shape) # (3, 1)
# np.newaxis 사용 (더 읽기 쉬움)
print(arr[np.newaxis, :].shape) # (1, 3)
print(arr[:, np.newaxis].shape) # (3, 1)결론
numpy.reshape()는 NumPy 라이브러리에서 가장 자주 사용되는 함수 중 하나입니다. 데이터를 복사하지 않고(대부분의 경우) 1D, 2D, 3D 및 그 이상의 차원 배열 간에 변환할 수 있게 해줍니다. 기억해야 할 핵심 포인트:
- 전체 요소 수는 reshape 전후로 동일하게 유지되어야 합니다.
- 하나의 차원에
-1을 사용하여 NumPy가 자동으로 계산하게 합니다. reshape()는 보통 복사본이 아닌 뷰를 반환합니다. 뷰에 대한 변경은 원래 배열에 영향을 미칩니다.- 기본
order='C'는 행별로 요소를 채웁니다. MATLAB이나 Fortran의 열 우선 데이터에는order='F'를 사용합니다. - scikit-learn이 1D 배열에 대해 불평하면
.reshape(-1, 1)이 해결책입니다.
이러한 패턴을 마스터하면, 머신러닝용 테이블 데이터를 준비하든 딥러닝용 이미지 텐서를 reshape하든, 형상 불일치를 자신 있게 처리할 수 있습니다.