Menu
CoddyTech

NumPy 치트시트

마지막 업데이트

배열 만들기

배열은 한 가지 타입의 값을 차원 수에 관계없이 격자 형태로 담아요.

작업코드
NumPy 임포트import numpy as np
리스트로 만들기np.array([1, 2, 3])
중첩 리스트로 2D 배열np.array([[1, 2, 3], [4, 5, 6]])
0, 1, 지정한 값으로 채우기np.zeros((2, 3)), np.ones(4), np.full((2, 2), 7)
간격 지정 범위 (끝 제외)np.arange(0, 10, 2) # [0 2 4 6 8]
균등 간격 n개 점 (끝 포함)np.linspace(0, 1, 5) # [0. 0.25 0.5 0.75 1.]
단위 행렬np.eye(3)
다른 배열과 같은 형태np.zeros_like(m), np.ones_like(m)
원소 타입 지정np.array([1, 2, 3], dtype=np.float32)
좌표 격자xx, yy = np.meshgrid(np.arange(3), np.arange(2))

배열 살펴보기

작업코드
shape: 각 차원의 크기m.shape # (3, 4)
차원 수m.ndim # 2
원소 개수m.size # 12
원소 타입m.dtype # int64
타입 변환m.astype(np.float64)
첫 번째 차원의 길이len(m) # 3
Python 리스트로 되돌리기m.tolist()
소수점 자릿수 줄여 출력np.set_printoptions(precision=3, suppress=True)

인덱싱과 슬라이싱

슬라이스는 뷰라서 원본 배열과 메모리를 공유해요. 마스크와 인덱스 리스트는 복사본을 반환해요.

작업코드
첫 번째와 마지막 원소a[0], a[-1]
start:stop 슬라이스 (stop 제외)a[1:4] # [20 30 40]
하나 걸러 원소, 역순a[::2], a[::-1]
2D 배열의 원소 하나m[1, 2] # 6
행 하나, 열 하나m[0], m[:, 1]
행과 열 블록m[:2, 1:3]
조건에 맞는 원소a[a > 25] # [30 40 50]
조건 조합a[(a > 15) & (a < 45)]
위치 리스트로 선택a[[0, 2, 4]]
조건에 맞는 위치np.flatnonzero(a > 25) # [2 3 4]
원소별로 값 선택np.where(a > 25, a, 0)
슬라이스 수정 전에 복사part = a[1:3].copy()
마스크로 값 설정a[a > 40] = 0

연산과 브로드캐스팅

연산자는 원소별로 동작해요. 브로드캐스팅은 스칼라, 행, 열을 늘려 다른 배열의 형태에 맞춰요.

작업코드
원소별 산술 연산x + y, x - y, x * y, x / y, x ** 2
스칼라와 연산x * 10
제곱근, 지수, 로그np.sqrt(x), np.exp(x), np.log(x)
절댓값, 반올림np.abs(x - 5), np.round(x / 3, 2)
값을 범위 안으로 제한np.clip(x, 2, 8)
원소별 최댓값np.maximum(x, 3)
내적x @ y # 37.0
열마다 중심화 (행 브로드캐스트)m - m.mean(axis=0)
행마다 스케일 조정 (열 브로드캐스트)m / m.sum(axis=1, keepdims=True)
실수를 안전하게 비교np.isclose(0.1 + 0.2, 0.3) # True, np.allclose(x, y)
삼각함수와 pinp.sin(np.pi / 2) # 1.0

축 방향 집계

axis=0은 행 방향(위에서 아래)으로 계산해서 열마다 결과 하나를 내요. axis=1은 열 방향(왼쪽에서 오른쪽)으로 계산해서 행마다 결과 하나를 내요.

작업코드
모든 원소의 합계m.sum() # 21
열마다 결과 하나m.sum(axis=0) # [5 7 9]
행마다 결과 하나m.sum(axis=1) # [ 6 15]
평균과 표준편차m.mean(), m.std(), m.mean(axis=0)
최솟값, 최댓값m.min(), m.max(axis=1)
최댓값의 위치m.argmax(), m.argmax(axis=1)
중앙값과 백분위수np.median(m), np.percentile(m, [25, 50, 75])
누적 합계np.cumsum(m, axis=1)
모든 원소의 곱m.prod() # 720
any, all, 개수(m > 4).any(), (m > 0).all(), np.count_nonzero(m > 2)

형태 바꾸기와 합치기

reshape는 원소는 그대로 두고 형태만 바꾸므로 전체 크기가 같아야 해요.

작업코드
새 형태a.reshape(2, 3)
크기 하나는 NumPy가 계산a.reshape(3, -1), a.reshape(-1, 1)
1D로 펼치기m.ravel(), m.flatten()
전치m.T
차원 추가a[:, np.newaxis], np.expand_dims(a, axis=0)
크기가 1인 차원 제거np.squeeze(np.ones((1, 3, 1)))
기존 축을 따라 연결np.concatenate([a, a])
행 또는 열로 쌓기np.vstack([m, m]), np.hstack([m, m])
1D 배열을 열로np.column_stack([a, a ** 2])
새 축을 따라 쌓기np.stack([a, a], axis=0) # shape (2, 6)
여러 조각으로 나누기np.split(a, 3), np.array_split(a, 4)
반복 또는 타일링np.repeat([1, 2], 2) # [1 1 2 2], np.tile([1, 2], 2) # [1 2 1 2]

정렬, 검색, 고유값

작업코드
정렬된 복사본np.sort(a)
큰 값부터np.sort(a)[::-1]
정렬 순서의 위치np.argsort(a)
가장 큰 값 3개np.sort(a)[-3:]
고유값과 개수values, counts = np.unique(a, return_counts=True)
NumPy 2 이름 (unique_values는 정렬되지 않을 수 있음)np.unique_values(a), np.unique_counts(a)
각 원소가 리스트에 있는지np.isin(a, [1, 9])
정렬된 배열의 삽입 위치np.searchsorted([1, 3, 5, 7], 4) # 2
집합 연산np.intersect1d(a, [1, 2, 10]), np.union1d(a, [10]), np.setdiff1d(a, [1])
한 열 기준으로 행 정렬m[m[:, 1].argsort()]

난수

시드를 지정한 Generator를 하나 만들고 모든 난수를 거기서 뽑으세요. 그러면 실행할 때마다 같은 결과가 나와요.

작업코드
시드 지정 생성기rng = np.random.default_rng(42)
[0, 1) 범위의 실수rng.random(3)
정수 (상한 제외)rng.integers(1, 7, size=10)
정규분포rng.normal(loc=0, scale=1, size=(2, 3))
범위 안의 균등분포 실수rng.uniform(5, 10, size=4)
리스트에서 뽑기rng.choice(["a", "b", "c"], size=5)
중복 없이 뽑기rng.choice(10, size=3, replace=False)
가중치를 두고 뽑기rng.choice(["H", "T"], size=10, p=[0.7, 0.3])
섞은 복사본, 제자리 섞기rng.permutation(a), rng.shuffle(a)
이항분포와 포아송분포rng.binomial(10, 0.5, size=5), rng.poisson(3, size=5)

선형대수

작업코드
행렬 곱A @ A
Ax = b 풀기np.linalg.solve(A, b) # [0.8 1.4]
역행렬과 행렬식np.linalg.inv(A), np.linalg.det(A)
벡터 길이np.linalg.norm(b)
고윳값과 고유벡터values, vectors = np.linalg.eig(A)
직선 피팅slope, intercept = np.polyfit(x, y, 1)
외적np.outer([1, 2], [3, 4])
대각 성분과 대각합np.diag(A), np.trace(A)

결측값과 특수값

np.nan은 결측 실수를 나타내요. 이 값과 연산하면 결과가 모두 nan이 되니 nan 함수나 마스크를 쓰세요.

작업코드
결측값np.nan
결측값 찾기np.isnan(v), np.isnan(v).sum()
결측값 제거v[~np.isnan(v)]
결측값과 무한대 바꾸기np.nan_to_num(v, nan=0.0, posinf=0.0)
무한대와 유한값 확인np.inf, np.isfinite(v)
NaN을 건너뛰는 통계np.nanmean(v[:3]) # 2.0, np.nanmax(v)

저장과 불러오기

작업코드
배열 하나, 바이너리 파일np.save("data.npy", m), m = np.load("data.npy")
여러 배열을 한 파일에np.savez("data.npz", x=x, y=y), np.load("data.npz")["x"]
CSV 텍스트 저장np.savetxt("data.csv", m, delimiter=",", fmt="%d")
CSV 텍스트 읽기np.loadtxt("data.csv", delimiter=",")

NumPy 2: 예전 이름과 지금 쓰는 이름

NumPy 2에서 많은 별칭이 제거되어, 예전 튜토리얼에서 복사한 코드는 AttributeError로 실패할 수 있어요.

작업NumPy 2예전 방식
결측값np.nannp.NaN
무한대np.infnp.Inf
64비트 실수 타입np.float64np.float_
곡선 아래 넓이np.trapezoid(y, x)np.trapz(y, x)
각 원소가 다른 배열에 있는지np.isin(a, b)np.in1d(a, b)
행 쌓기np.vstack([a, a])np.row_stack([a, a])
곱np.prod(a)np.product(a)
난수rng = np.random.default_rng(0) rng.random(3)np.random.seed(0) np.random.rand(3)

데이터 과학 코드의 기반이 되는 NumPy 호출을 작업별로 모았어요. 배열 만들기, 살펴보기, 인덱싱과 슬라이싱, 원소별 연산, 축 방향 집계, 형태 바꾸기와 합치기, 정렬과 검색, 난수 생성, 선형대수 풀이까지 담았어요. 각 행에는 바로 붙여 넣을 수 있는 짧은 코드와 무엇을 하는지 설명하는 한 줄이 있어요.

모든 내용은 Coddy에서 실행하는 버전인 NumPy 2 기준이고, 마지막 표에는 NumPy 2에서 제거된 이름과 대신 쓸 코드를 함께 정리했어요. 대부분의 예제는 a = np.array([3, 1, 4, 1, 5, 9, 2, 6])와 m = np.arange(12).reshape(3, 4)를 사용해요. Python 자체가 처음이라면 Python 치트시트와 Python 플레이그라운드부터 시작하고, pandas, Matplotlib, scikit-learn 치트시트도 함께 띄워 두세요.

NumPy 치트시트 자주 묻는 질문

이 NumPy 치트시트는 무료인가요?
네. 이 NumPy 치트시트는 완전히 무료이고 가입도 필요 없어요. 북마크해 두거나 브라우저에서 PDF로 인쇄해 두고, reshape, 축 방향 합계, 난수 생성의 정확한 호출이 필요할 때마다 다시 찾아오세요.
이 치트시트는 어떤 NumPy 버전을 다루나요?
NumPy 2예요. 모든 코드는 Coddy에서 실행하는 버전인 NumPy 2.4에서 동작해요. NumPy 2에서는 np.NaN, np.float_, np.trapz, np.in1d 같은 별칭이 제거되었기 때문에, 마지막 표에 각 별칭과 현재 이름을 나란히 정리했어요.
NumPy에서 axis=0은 무슨 뜻인가요?
axis는 접혀서 사라지는 차원이에요. 2D 배열에서 axis=0은 행 방향으로 내려가며 계산하므로 m.sum(axis=0)은 열마다 합계 하나를 반환해요. axis=1은 열 방향으로 가로질러 계산하고 행마다 합계 하나를 반환해요. axis를 지정하지 않으면 함수는 모든 원소를 사용해요.
뷰와 복사본의 차이는 무엇인가요?
a[1:3] 같은 슬라이스는 뷰예요. a와 메모리를 공유하므로 슬라이스를 바꾸면 a도 바뀌어요. a[a > 2]나 a[[0, 2]] 같은 불리언 마스크와 인덱스 리스트는 복사본을 반환해요. 독립된 배열이 필요하면 .copy()를 호출하세요.
Python 리스트 대신 NumPy 배열을 쓰는 이유는 무엇인가요?
배열은 한 가지 타입을 하나의 메모리 블록에 저장하므로, 배열 전체에 대한 연산이 컴파일된 코드로 실행되어 Python 반복문보다 몇 배나 빠른 경우가 많아요. a * 2는 모든 원소를 두 배로 만들지만 [1, 2] * 2는 리스트를 반복해요. pandas와 scikit-learn도 NumPy 배열 위에 만들어졌어요.
np.random.seed와 default_rng 중 무엇을 써야 하나요?
rng = np.random.default_rng(seed)를 쓰고 rng.normal()이나 rng.integers()처럼 rng의 메서드를 호출하세요. 이것이 권장 API이며, 더 좋은 난수 스트림을 제공하고 숨겨진 전역 상태가 없어요. np.random.seed와 np.random.rand도 여전히 동작하지만 레거시 인터페이스예요.
NumPy 코드를 온라인에서 실행할 수 있나요?
네. 무료 Matplotlib 플레이그라운드는 NumPy, pandas, Matplotlib, scikit-learn이 포함된 Python을 브라우저에서 실행해요. 이 치트시트의 코드를 아무거나 붙여 넣고 설치 없이 바로 실행해 보세요. Coddy의 머신러닝 코스는 실제 데이터를 다루는 과정에서 NumPy를 단계별로 가르쳐요.
Coddy 프로그래밍 언어 일러스트

Coddy로 NumPy 배우기

시작하기