NumPy가 필요한 이유
# Python 리스트 — 느림
data = list(range(1_000_000))
result = [x * 2 for x in data] # 반복문 필요
# NumPy 배열 — 빠름 (C로 구현됨)
import numpy as np
arr = np.arange(1_000_000)
result = arr * 2 # 벡터 연산, 약 100배 빠름
ndarray 생성
import numpy as np
# 리스트에서
arr1d = np.array([1, 2, 3, 4, 5])
arr2d = np.array([[1, 2, 3], [4, 5, 6]])
print(arr1d.shape) # (5,)
print(arr2d.shape) # (2, 3)
print(arr2d.dtype) # int64
# 특수 배열
zeros = np.zeros((3, 4)) # 0으로 채움
ones = np.ones((2, 3), dtype=float)
eye = np.eye(3) # 단위 행렬
empty = np.empty((2, 2)) # 초기화 안 함
# 범위
arange = np.arange(0, 10, 2) # [0, 2, 4, 6, 8]
linspace = np.linspace(0, 1, 5) # [0, 0.25, 0.5, 0.75, 1.0]
# 랜덤
rng = np.random.default_rng(42) # 시드 고정
rand = rng.random((3, 3)) # 0~1 균등분포
normal = rng.normal(0, 1, (1000,)) # 정규분포
인덱싱과 슬라이싱
arr = np.array([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]])
# 기본 인덱싱
print(arr[0, 0]) # 1
print(arr[1, 2]) # 7
print(arr[-1, -1]) # 12
# 슬라이싱
print(arr[0, :]) # [1, 2, 3, 4] (첫 번째 행)
print(arr[:, 1]) # [2, 6, 10] (두 번째 열)
print(arr[0:2, 1:3]) # [[2, 3], [6, 7]]
# 불리언 인덱싱
mask = arr > 6
print(arr[mask]) # [7, 8, 9, 10, 11, 12]
배열 연산
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
# 원소별 연산
print(a + b) # [5, 7, 9]
print(a * b) # [4, 10, 18]
print(a ** 2) # [1, 4, 9]
# 행렬 곱
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
print(A @ B) # [[19, 22], [43, 50]]
브로드캐스팅
크기가 다른 배열 간 연산을 자동으로 확장합니다.
# (3,) + (3, 1) → 브로드캐스팅
row = np.array([1, 2, 3]) # shape: (3,)
col = np.array([[10], [20]]) # shape: (2, 1)
result = row + col
# [[11, 12, 13], ← row + 10
# [21, 22, 23]] ← row + 20
# 실용적인 예: 각 행에서 평균 빼기 (정규화)
data = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
mean = data.mean(axis=1, keepdims=True) # 행별 평균, shape: (3, 1)
normalized = data - mean # 브로드캐스팅
집계 함수
arr = np.array([[1, 2, 3], [4, 5, 6]])
print(arr.sum()) # 21 (전체 합)
print(arr.sum(axis=0)) # [5, 7, 9] (열별 합)
print(arr.sum(axis=1)) # [6, 15] (행별 합)
print(arr.mean()) # 3.5
print(arr.std()) # 표준편차
print(arr.max(), arr.min())
print(arr.argmax()) # 최대값 위치 (평탄화된 인덱스)
print(np.percentile(arr, 75)) # 75번째 퍼센타일
배열 변환
arr = np.arange(12)
# 형태 변경
reshaped = arr.reshape(3, 4) # (3, 4)
flattened = reshaped.flatten()
# 전치
transposed = reshaped.T # (4, 3)
# 정렬
data = np.array([3, 1, 4, 1, 5, 9])
sorted_arr = np.sort(data) # 오름차순
sort_idx = np.argsort(data) # 정렬 인덱스
# 유니크
unique, counts = np.unique(data, return_counts=True)
정리
| 기능 | 코드 |
|---|---|
| 배열 생성 | np.array(), np.zeros(), np.arange() |
| 슬라이싱 | arr[0:2, 1:3] |
| 불리언 마스크 | arr[arr > 0] |
| 집계 | .sum(), .mean(), .std() |
| 형태 변경 | .reshape(), .T |
| 행렬 곱 | A @ B |
다음 편에서는 Pandas 기초 — 표 형태의 데이터를 다루는 DataFrame을 배웁니다.