NumPy Concatenate: np.concatenate, vstack, hstack로 배열 결합하기
Updated on
배열 결합은 수치 컴퓨팅에서 가장 일반적인 연산 중 하나입니다. 처리를 위해 데이터를 분할한 후 다시 조립해야 합니다. 여러 소스에서 특성을 하나의 행렬로 로드합니다. 앙상블을 위해 여러 모델의 예측을 스택합니다. Python 리스트를 사용하여 루프나 +로 배열을 결합하면 성능이 저하되고 불필요한 복사가 생성됩니다.
NumPy는 C 속도로 작동하며 어떤 축을 따라 연결할지 정밀하게 제어할 수 있는 배열 결합 전용 함수를 제공합니다. 이 가이드에서는 np.concatenate(), np.vstack(), np.hstack(), np.stack()과 그 사용 사례를 다룹니다.
np.concatenate() -- 핵심 함수
np.concatenate()는 기존 축을 따라 배열 시퀀스를 결합합니다.
1D 배열
import numpy as np
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
c = np.array([7, 8, 9])
result = np.concatenate([a, b, c])
print(result) # [1 2 3 4 5 6 7 8 9]
print(result.shape) # (9,)행 방향 2D 배열 (axis=0)
import numpy as np
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
# 수직으로 스택 (행 추가)
result = np.concatenate([a, b], axis=0)
print(result)
# [[1 2]
# [3 4]
# [5 6]
# [7 8]]
print(result.shape) # (4, 2)열 방향 2D 배열 (axis=1)
import numpy as np
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
# 수평으로 스택 (열 추가)
result = np.concatenate([a, b], axis=1)
print(result)
# [[1 2 5 6]
# [3 4 7 8]]
print(result.shape) # (2, 4)Shape 요구사항
모든 배열은 연결 축을 제외하고 동일한 형태를 가져야 합니다.
import numpy as np
a = np.ones((3, 4)) # 3행, 4열
b = np.zeros((2, 4)) # 2행, 4열
# OK: 행 수가 다르지만, 열 수가 같음, axis=0
result = np.concatenate([a, b], axis=0)
print(result.shape) # (5, 4)
# 오류: 열 수가 다름
c = np.ones((3, 5))
# np.concatenate([a, c], axis=0) # ValueError: dimensions don't matchnp.vstack() -- 수직 스택
np.vstack()는 배열을 수직으로(축 0을 따라) 스택합니다. np.concatenate(arrays, axis=0)과 동일하지만 1D 배열을 단일 행으로 처리합니다.
import numpy as np
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
# vstack은 1D 배열을 행으로 처리
result = np.vstack([a, b])
print(result)
# [[1 2 3]
# [4 5 6]]
print(result.shape) # (2, 3)
# 2D 배열의 경우
c = np.array([[1, 2], [3, 4]])
d = np.array([[5, 6]])
result = np.vstack([c, d])
print(result)
# [[1 2]
# [3 4]
# [5 6]]np.hstack() -- 수평 스택
np.hstack()는 배열을 수평으로 스택합니다(2D의 경우 축 1, 1D의 경우 축 0).
import numpy as np
# 1D 배열: np.concatenate처럼 연결
a = np.array([1, 2, 3])
b = np.array([4, 5])
result = np.hstack([a, b])
print(result) # [1 2 3 4 5]
# 2D 배열: 열 추가
c = np.array([[1], [2], [3]])
d = np.array([[4], [5], [6]])
result = np.hstack([c, d])
print(result)
# [[1 4]
# [2 5]
# [3 6]]np.stack() -- 새로운 축 생성
concatenate와 달리 stack은 새로운 축을 따라 배열을 결합하여 차원 수를 1 증가시킵니다.
import numpy as np
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
# 새로운 축 0을 따라 스택 (기본값)
result = np.stack([a, b])
print(result)
# [[1 2 3]
# [4 5 6]]
print(result.shape) # (2, 3)
# 새로운 축 1을 따라 스택
result = np.stack([a, b], axis=1)
print(result)
# [[1 4]
# [2 5]
# [3 6]]
print(result.shape) # (3, 2)np.stack()에서는 모든 입력 배열이 동일한 형태를 가져야 합니다.
함수 비교
| 함수 | 축 | 새 축 생성? | 1D 입력 처리 |
|---|---|---|---|
np.concatenate | 기존 (기본값 0) | 아니오 | 그대로 연결 |
np.vstack | 0 (수직) | 아니오 | 1D를 행으로 처리 |
np.hstack | 1 (수평) | 아니오 | 1D 배열 연결 |
np.stack | 새 축 | 예 (+1 차원) | 새 차원 생성 |
np.column_stack | 1 | 아니오 | 1D를 열로 처리 |
np.row_stack | 0 | 아니오 | vstack과 동일 |
실용적인 예제
머신러닝을 위한 특성 결합
import numpy as np
# 다양한 소스의 특성 배열
ages = np.array([25, 30, 35, 40])
incomes = np.array([50000, 60000, 75000, 90000])
scores = np.array([720, 680, 750, 800])
# 열로 스택하여 특성 행렬 생성
X = np.column_stack([ages, incomes, scores])
print(X)
# [[ 25 50000 720]
# [ 30 60000 680]
# [ 35 75000 750]
# [ 40 90000 800]]
print(X.shape) # (4, 3)배치 처리 결과
import numpy as np
# 데이터를 배치로 처리하고 결과 결합
results = []
for batch_start in range(0, 100, 25):
batch = np.random.randn(25, 10) # 25개 샘플, 10개 특성
processed = batch * 2 + 1 # 일부 처리
results.append(processed)
# 모든 배치를 수직으로 결합
all_results = np.vstack(results)
print(all_results.shape) # (100, 10)이미지 처리 -- 채널 결합
import numpy as np
height, width = 100, 100
# 개별 색상 채널
red = np.random.randint(0, 256, (height, width))
green = np.random.randint(0, 256, (height, width))
blue = np.random.randint(0, 256, (height, width))
# RGB 이미지로 결합
rgb_image = np.stack([red, green, blue], axis=2)
print(rgb_image.shape) # (100, 100, 3)결합된 데이터 시각화
다양한 소스의 배열을 연결한 후, PyGWalker (opens in a new tab)를 사용하면 Jupyter에서 결합된 데이터셋을 인터랙티브하게 탐색할 수 있습니다:
import pandas as pd
import pygwalker as pyg
# 연결된 배열을 DataFrame으로 변환
df = pd.DataFrame(X, columns=['age', 'income', 'score'])
walker = pyg.walk(df)FAQ
np.concatenate와 np.stack의 차이점은 무엇인가요?
np.concatenate는 차원 수를 변경하지 않고 기존 축을 따라 배열을 결합합니다. np.stack은 새로운 축을 따라 배열을 결합하여 차원을 하나 추가합니다. 예를 들어, 두 개의 (3,) 배열을 concatenate로 스택하면 (6,)이 되고, stack으로 하면 (2, 3)이 됩니다.
np.concatenate에서 axis는 무엇을 의미하나요?
axis 매개변수는 어떤 차원을 따라 결합할지 지정합니다. axis=0은 행을 따라 연결(더 많은 행 추가), axis=1은 열을 따라 연결(더 많은 열 추가)합니다. 2D 배열의 경우 axis=0은 수직 스택이고 axis=1은 수평 스택입니다.
vstack, hstack, concatenate는 언제 사용해야 하나요?
행을 추가하려면(수직 스택) vstack, 열을 추가하려면(수평 스택) hstack, 임의의 축을 지정해야 할 때는 concatenate를 사용하세요. vstack과 hstack은 concatenate보다 1D 배열을 더 직관적으로 처리하는 편의 함수입니다.
배열을 연결할 때 ValueError가 발생하는 이유는 무엇인가요?
모든 배열은 연결 축을 제외하고 동일한 형태를 가져야 합니다. axis=0을 따라 연결하는 경우, 모든 배열은 동일한 열 수를 가져야 합니다. 연결 전에 array.shape로 형태를 확인하세요.
서로 다른 차원의 배열을 연결하려면 어떻게 하나요?
먼저 배열을 호환 가능한 차원으로 변환하세요. np.expand_dims(array, axis)로 차원을 추가하거나 array.reshape(new_shape)를 사용하세요. 예를 들어, 1D 배열을 2D 배열과 vstack하려면 1D 배열을 변환합니다: array.reshape(1, -1).
결론
NumPy는 배열 결합을 위한 완전한 도구 세트를 제공합니다: 어떤 축을 따라서든 범용 결합을 위한 np.concatenate(), 직관적인 수직/수평 스택을 위한 np.vstack()/np.hstack(), 새로운 차원을 생성해야 할 때의 np.stack(). concatenate는 기존 축을 따라 결합하고 stack은 새로운 축을 생성한다는 것을 기억하세요. 차원을 신중하게 맞추고, 일반적인 행/열 연산에서 가장 읽기 쉬운 코드를 위해 vstack/hstack을 사용하세요.