NumPy 소개
NumPy는 Python에서 과학 계산을 위한 핵심 라이브러리로, 동일한 데이터 타입의 요소들로 구성된 다차원 배열(ndarray)을 효율적으로 처리할 수 있게 해줍니다. 배열 내 모든 요소는 동일한 크기의 메모리 블록을 차지하며, 벡터 및 행렬 연산, 선형 대수, 푸리에 변환, 난수 생성 등 다양한 수치 연산 기능을 제공합니다.
배열 생성 방법
numpy.array() — 기본 배열 생성
가장 일반적인 배열 생성 함수입니다. 리스트, 튜플, 반복 가능한 객체 등을 입력으로 받아 ndarray를 반환합니다.
import numpy as np
# 리스트 및 튜플로부터 생성
arr1 = np.array([0, 1, 2, 3])
arr2 = np.array((4, 5, 6))
# 자료형 명시 (dtype)
arr_float = np.array([1.1, 2.9], dtype='int32') # 정수로 변환됨
arr_str = np.array(['a', 'b'], dtype='U10') # 유니코드 문자열
특수 배열 생성 함수
- np.zeros(shape): 주어진 형태의 0으로 채워진 배열 생성
- np.ones(shape): 주어진 형태의 1로 채워진 배열 생성
- np.arange(start, stop, step): 일정 간격의 숫자 배열 생성 (stop 미포함)
- np.linspace(start, stop, num): 시작과 끝 사이를 균등하게 나눈 num개의 값 생성 (기본 포함)
- np.logspace(start, stop, num, base=10): 로그 스케일 상에서 균등한 간격의 배열 생성
# 예시
zeros_2d = np.zeros((2, 3))
linear_seq = np.linspace(0, 1, 5) # [0.0, 0.25, 0.5, 0.75, 1.0]
log_seq = np.logspace(0, 2, 3, base=2) # [1.0, 2.0, 4.0]
난수 배열 생성
np.random 모듈을 통해 다양한 분포의 난수 생성 가능:
# [0, 1) 구간 균일분포
uniform = np.random.rand(2, 3)
# 표준정규분포 (평균 0, 표준편차 1)
normal = np.random.randn(2, 3)
# 지정된 범위의 정수 난수
integers = np.random.randint(10, 20, size=(2, 3))
# 시드 고정 (재현성 보장)
np.random.seed(123)
배열 속성 확인
생성된 배열의 구조와 정보는 다음 속성들을 통해 확인할 수 있습니다:
- ndim: 차원 수 (랭크)
- shape: 각 차원의 크기를 담은 튜플
- size: 전체 요소 개수
- dtype: 요소의 데이터 타입
- itemsize: 각 요소의 바이트 크기
- nbytes: 전체 배열이 차지하는 바이트 수 (size × itemsize)
arr = np.ones((3, 4), dtype=np.float64)
print(arr.shape) # (3, 4)
print(arr.dtype) # float64
print(arr.nbytes) # 96 (3*4*8)
배열 형태 변경
reshape()
요소 수를 유지한 채 배열의 형상을 재구성합니다. -1을 사용하면 해당 차원을 자동 추론합니다.
arr = np.arange(6)
reshaped = arr.reshape(2, 3) # 2x3 배열
flattened = arr.reshape(-1) # 1차원으로 펼침
resize()
원본 배열의 크기를 직접 변경하거나, 새 배열을 만들어 크기를 조정합니다. 원래 크기보다 클 경우 반복해서 채우고, 작을 경우 잘라냅니다.
arr = np.array([1, 2, 3])
resized = np.resize(arr, (5,)) # [1, 2, 3, 1, 2]
arr.resize((5,)) # 원본 배열 수정
flatten() vs ravel()
둘 다 다차원 배열을 1차원으로 만듭니다.
- flatten(): 항상 새로운 배열(사본)을 반환
- ravel(): 가능하면 원본 배열의 뷰(view)를 반환하여 메모리 효율적
arr_2d = np.array([[1, 2], [3, 4]])
flat_copy = arr_2d.flatten()
view_like = arr_2d.ravel()
전치 (transpose / T)
행과 열을 교환하거나 고차원 배열의 축 순서를 변경합니다.
matrix = np.array([[1, 2], [3, 4]])
transposed = matrix.T # 또는 np.transpose(matrix)
인덱싱과 슬라이싱
기본 인덱싱
단일 요소 접근은 정수 인덱스로 가능하며, 음수 인덱스는 뒤에서부터 참조합니다.
arr = np.array([10, 20, 30, 40])
print(arr[2]) # 30
print(arr[-1]) # 40
슬라이싱
부분 배열 추출. [start:stop:step] 형식 사용.
arr = np.arange(10)
print(arr[2:7:2]) # [2, 4, 6]
print(arr[::-1]) # 역순 [9, 8, ..., 0]
고급 인덱싱
- 정수 배열 인덱싱: 특정 위치의 요소들을 선택 (사본 반환)
- 불리언 인덱싱: 조건에 맞는 요소만 필터링 (사본 반환)
data = np.array([10, 15, 20, 25, 30])
# 정수 인덱싱
selected = data[[0, 2, 4]] # [10, 20, 30]
# 불리언 인덱싱
filtered = data[data > 20] # [25, 30]
수학 및 통계 연산
기본 산술 연산
배열 간 요소별(element-wise) 연산 지원:
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
addition = a + b # [5, 7, 9]
multiplication = a * b # [4, 10, 18]
power = a ** 2 # [1, 4, 9]
행렬 연산
- np.dot(): 벡터 내적 또는 행렬 곱셈
- @ 연산자 또는 np.matmul(): 배치 행렬 곱셈에 적합
- np.linalg.inv(): 역행렬 계산
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
matmul_result = A @ B # 행렬 곱
A_inv = np.linalg.inv(A) # 역행렬
브로드캐스팅 (Broadcasting)
형상이 다른 배열 간 연산 시, 작은 배열이 자동으로 확장되어 연산됩니다. 메모리 복사 없이 효율적입니다.
matrix = np.array([[1, 2], [3, 4]]) # (2, 2)
vector = np.array([10, 20]) # (2,)
result = matrix + vector # [[11, 22], [13, 24]]
통계 함수
배열 전체 또는 특정 축을 따라 통계값 계산 가능:
- sum(), mean(), std(), var(): 합, 평균, 표준편차, 분산
- min(), max(): 최솟값, 최댓값
- median(): 중앙값 (배열 메서드 아님)
values = np.array([[1, 2], [3, 4]])
total_sum = values.sum() # 10
column_mean = values.mean(axis=0) # [2.0, 3.0]
std_dev = values.std(ddof=1) # 표본 표준편차
배열 수정 및 검색
- np.append(): 배열 끝에 요소 추가 (새 배열 반환)
- np.insert(): 지정 위치에 요소 삽입
- np.delete(): 특정 인덱스 제거
- np.argwhere(): 조건을 만족하는 요소의 인덱스 반환
arr = np.array([1, 2, 3])
appended = np.append(arr, 4) # [1, 2, 3, 4]
indices = np.argwhere(arr > 1) # [[1], [2]]
기타 유용한 기능
중복 제거 및 정렬
- np.unique(): 중복 제거 후 정렬된 배열 반환
- np.sort(): 정렬된 사본 반환
- arr.sort(): 원본 배열을 제자리에서 정렬
data = np.array([3, 1, 2, 2, 3])
unique_vals = np.unique(data) # [1, 2, 3]
sorted_vals = np.sort(data) # [1, 2, 2, 3, 3]
데이터 타입 변환
astype() 메서드로 안전하게 타입 변환 가능:
float_arr = np.array([1.5, 2.7])
int_arr = float_arr.astype('int32') # [1, 2] (절삭)
bool_arr = np.array([True, False]).astype('int8') # [1, 0]
파일 입출력
텍스트 파일 읽기
np.loadtxt()는 CSV나 공백으로 구분된 텍스트 파일을 배열로 로드합니다.
# 예: data.csv
# 1,2,3
# 4,5,6
loaded = np.loadtxt('data.csv', delimiter=',', dtype='int32')