1. 데이터 처리 / 준비 / Transform
데이터 품질을 향상시키기 위해 도메인과 최종 산출물에 적합한 형태로 데이터를 가공하는 단계. 데이터의 형태, 규모, 싱글/분산, 메모리 환경 등에 따라 적절한 도구를 선택해야 함.
1.1 도구 별 특징
| 라이브러리 | 특징 | 베이스 언어 | 데이터 규모 |
| numpy | ndarray(다차원배열) 중심 수치 계산, 데이터 분석/처리의 근간 | C 기반 연산 | 소~중규모 |
| pandas | Series(1D), DataFrame(2D) 자료구조. 파이썬 데이터 분석 표준. 데이터를 한 번에 메모리에 로드 | Python + Cython + C (Single Core) | 중규모 (~ 수 GB) |
| polars | DataFrame, 지연처리 기반 최적화, 스트리밍/병렬처리 집중 | Rust / Apache Arrow | 대규모 (~ 수십 GB) |
| spark | RDD/DataFrame/DataSet, 분산처리 프레임워크. 클러스터 기반 작동 | Scala/Java/PySpark/RSpark | 초대규모 (~ TB 이상) |
처리해야 하는 데이터의 크기에 따라 도구를 잘 판단해 선택해야 함.
2. NumPy 개요
2.1 학습 포인트
- 데이터 → ndarray 변환 — 입력 데이터를 ndarray로 처리하는 흐름을 잘 이해해야 함
- 스칼라/벡터 연산 — 연산 단위에 집중할 필요가 있음
- 속도 특성 — 파이썬 리스트보다 빠른 이유를 기억해두면 좋음
- 상위 라이브러리의 베이스 — pandas, polars 등 대부분의 라이브러리가 numpy 기반
- 인덱싱 기법 — 다양한 인덱싱 방식 체크 필요
2.2 특징
- 속도 — 파이썬 리스트보다 최대 50배 빠름
- 용도 — 대규모 다차원 배열과 행렬 연산을 효율적으로 처리하는 핵심 과학 계산 라이브러리
- 활용 영역 — 수치 계산 분야의 필수, 머신러닝/딥러닝의 기반 기술
- 공식 표현 — The fundamental package for scientific computing with Python
2.3 자료구조
- ndarray — n차원의 배열
- 타입 동일성 — 배열의 모든 구성원의 타입은 동일해야 함
3. NumPy 기본
# Colab(.ipynb) 환경에서 구동
import numpy as np
np.__version__ # '2.0.2'
# np 모듈에 존재하는 함수/변수 개수 확인
len(dir(np)) # 약 532개
- import np — numpy의 관용적 alias
- dir(np) — 모듈 내 함수/변수 전체 확인
4. 배열 생성
4.1 생성 방식
- 기본 패턴 — 입력원(Raw Data)으로부터 생성
- 입력원 종류 — 리스트, 튜플, 다른 배열, Series, DataFrame, csv 등
- 출력 — ndarray
- 빈 배열(버퍼) — 값을 미리 채우지 않은 형태도 생성 가능
4.2 array() — 리스트로부터 배열 생성
datas = [1, 2, 3]
arr = np.array(datas)
arr, arr.shape, type(arr), arr.ndim, arr.dtype
# (array([1,2,3]), (3,), numpy.ndarray, 1, dtype('int64'))
- shape — 튜플로 표현된 형태 정보 (3,)
- type — numpy.ndarray
- ndim — 차원 수
- dtype — 데이터 타입. 정수 입력 시 기본 int64 적용
- 타입 적정성 체크 — int64가 적절한지 메모리 효율 관점에서 검토 필요
# 2차원 리스트 -> 2차원 배열
datas = [
[1, 2, 3],
[4, 5, 6]
]
arr = np.array(datas)
# shape=(2,3), ndim=2, dtype=int64
- 원본이 정수형이면 배열 타입은 int64 (값 1개당 8바이트 할당)
배열의 차원: 벡터(자연어 처리/벡터DB), 매트릭스(데이터 분석/ML), 스칼라·벡터 연산을 이해해야 행렬 연산까지 확장 가능.
4.3 asarray() — 카피 생성
깊은 카피 개념으로 원본과 분리된 새 배열을 생성.
arr2 = np.asarray(arr)
# 인덱싱 (차원 축소)
arr2[0] # array([1, 2, 3]) -> 1차원
arr2[0][0] # np.int64(1) -> 0차원(스칼라)
# 수정 후 원본 확인
arr2[0][0] = 100
# arr2만 변경, arr은 유지됨
- 인덱싱 1회 = 차원 축소 1회 — 2차원 → 1차원 → 스칼라
- 깊은 카피 — 원본과 메모리 분리됨
4.4 arange() — 연속된 수로 배열 생성
np.arange(5) # [0, 1, 2, 3, 4]
np.arange(0, 5, 1) # 동일
np.arange(0, 5, 2) # [0, 2, 4]
np.arange(0, 5, 0.5) # [0., 0.5, ..., 4.5]
- 기본 동작 — 시작값 <= x < 끝값 범위를 step 간격으로 구간화
- 인자 — (시작, 끝, 간격)
# 차원 조정
np.arange(16).reshape(4, 4)
np.arange(16).reshape(8, -1) # -1은 자동 계산
np.arange(16).reshape(2, -1, 4)
- reshape 제약 — 1차원 수 × 2차원 수 × ... = 총 데이터 수 일치 필수
- -1 지정 — 나머지 차원으로부터 자동 계산
- 불일치 시 — 에러 발생 (reshape(4, 3) 같은 경우)
4.5 zeros / ones / empty — 특수 형태 배열
np.zeros((2, 3)) # 모든 원소 0, dtype=float64
np.ones((2, 3)) # 모든 원소 1, dtype=float64
np.empty((2, 3)) # 초기화되지 않은 메모리(특정값/랜덤)
- 기본 dtype — float64
- 용도 — 형태(shape)만 부여하고 값은 채워야 하는 경우, 버퍼 역할, 수학적 특수 연산용
4.6 zeros_like / ones_like / empty_like — 형태 복사
대상 배열의 shape을 복사하여 0/1/특정값으로 채움.
arr2 = np.ones_like(arr)
# arr과 동일한 shape에 1로 채워진 배열 생성
- shape 복사 — 원본과 동일한 차원 구성
- 활용 — 동일 크기의 보조 배열이 필요할 때
4.7 eye / identity — 단위 행렬
np.eye(3, 3)
np.identity(3)
# [[1, 0, 0],
# [0, 1, 0],
# [0, 0, 1]]
np.eye(3, 4) # 비정방형도 가능
- 대각선 1, 나머지 0 — 단위 행렬 구성
- eye는 비정방형도 허용 — identity는 정방형만 가능
4.8 random — 정규분포 기반 난수
arr = np.random.randn(2, 3, 4)
# 표준편차 1, 평균 0인 정규분포 난수 생성
# 조건식 -> 불리언 배열
arr > 0
- randn — 표준정규분포(평균 0, 표준편차 1) 난수 발생
- 분포 범위 — 정규분포에 맞춰 자동 조정
- 차원 확인 — 출력 시 대괄호 [[[ 개수로 차원 빠르게 판단 가능
- 활용 — 임의 벡터/매트릭스 구성, DL 모델의 초기 파라미터(CNN 커널값), GAN의 노이즈 벡터 등
스칼라(0차원) vs 행렬(3차원) 연산 시, 스칼라가 모든 구성원을 방문해 비교/연산을 수행한 결과로 대체됨 (브로드캐스팅).
5. 기본 연산
5.1 배열 vs 스칼라
배열의 모든 구성원에 스칼라 값이 일일이 접근해 연산을 수행.
arr = np.random.randn(2, 3)
arr + 10
arr - 10
arr * 10
arr / 10
- 모든 멤버 접근 후 연산 → 결과 대체 — pandas의 apply, 파이썬의 map과 유사한 동작
5.2 배열 vs 배열
동일 크기
같은 위치의 원소끼리 연산 수행.
arr + arr # 같은 위치 원소 합
arr - arr # 모두 0
arr * arr # 같은 위치 원소 곱
arr / arr # 모두 1
- 요소별 연산(element-wise) — shape이 동일할 때 위치 기준으로 매칭
다른 크기 — 브로드캐스팅
연산이 가능하도록 차원을 자동 확장하여 처리.
- 원칙 — 연산이 맞닿은 행/열이 일치하거나 1일 때만 가능
- 조건 불충족 시 — 에러 발생
- 메커니즘 — 부족한 차원을 스크래치(복제)하여 연산
6. 타입
배열 구성원을 메모리에 할당하려면 타입 지정이 필요. 배열 당 타입은 하나로 고유함.
6.1 유형
| 유형 | 종류 |
| 정수형 | int8, int16, int32, int64 (기본) |
| 부호 없는 정수형 | uint8, uint16, uint32, uint64 |
| 실수형 | float16, float32, float64 (기본) |
| 복소수형 | complex64, complex128 |
| 논리형 | bool |
| 객체형 | 문자열 등 |
- 확인 방법 — 배열.dtype
- float8은 없음 — 실수형은 16부터 시작
arr = np.array([1, 2, 3])
arr.dtype # dtype('int64')
arr = np.array([1, 2, 3], dtype=np.uint8)
arr.dtype # dtype('uint8')
명시적 형변환은 데이터 손실 가능, 암묵적 형변환은 손실은 없되 메모리 낭비 가능.
6.2 astype() — 타입 변경
arr = np.array([1, 2, 256])
# (array([1, 2, 256]), dtype('int64'))
tmp = arr.astype(np.int8)
# (array([1, 2, 0], dtype=int8), dtype('int8'))
- int64 → int8 — 8바이트 → 1바이트, 7바이트 정보 손실
- 256 → 0 변환 이유 — int8은 1바이트(8비트)만 보유하므로 상위 비트가 잘려나감
- 비트 표현 — 0...0100000000 (256) → 하위 8비트 00000000만 남음 → 0
- 257이었다면 — 0...0100000001 → 00000001 → 1 보존
7. 데이터 추출
7.1 인덱싱
배열[인덱스] 형태로 접근. 차원 축소 개념.
arr = np.arange(1, 7).reshape((2, 3))
# [[1, 2, 3],
# [4, 5, 6]]
arr[0] # array([1, 2, 3]) -> 2D -> 1D
arr[0][-1] # np.int64(3) -> 1D -> 0D
arr[0, -1] # np.int64(3) -> 좌표 표기
- 인덱싱 1회 = 차원 축소 1회
- 좌표 표기 — [0, -1]처럼 차원별 인덱스를 쉼표로 분리
7.2 슬라이싱
배열[시작:끝:간격] 형태로 추출. 차원 유지 개념.
arr2 = arr[:] # 전체 카피
arr2[0] = 100 # 0번 행 전체 100으로 일괄 처리
arr = np.arange(16).reshape(2, -1)
arr[:, :] # 원본 카피 (양쪽 차원 전부)
arr[:1, :1] # array([[0]]) -> 2차원 유지
arr[:1, 0] # array([0]) -> 1회 차원 축소
- : 단독 — 해당 차원 전체 선택
- 슬라이싱은 차원 유지 — 결과가 단일 원소여도 배열 형태로 보존
- 결측치 처리 패턴 — arr2[0] = 100처럼 슬라이싱 후 일괄 대입
7.3 불리언 인덱싱
조건식의 불리언 결과를 활용해 만족 데이터를 추출/필터링.
arr = np.random.randn(4, 10)
# 음수를 결측치로 가정 -> 0으로 치환
arr[arr < 0] = 0
- 조건식 결과 — 불리언 배열로 반환됨
- 활용 패턴 — arr[조건] = 값 형태로 대상 특정 후 변경
- pandas 대응 — fillna 등 매개변수 기반 기능과 유사한 흐름
데이터 분석에서 가장 빈번하게 사용하는 패턴 중 하나.
7.4 팬시 인덱싱
데이터의 위치를 직접 지정해 추출. 방향성/연속성 없이 임의 순서 추출 가능.
arr = np.arange(32).reshape(-1, 4)
arr[[3, 0, 4, 5]]
# 3행, 0행, 4행, 5행 순으로 추출
arr[[3, 0, 4, 5], [2, 1, 0, 3]]
# 차원별 인덱스 지정 -> array([14, 1, 16, 23])
- 임의 순서 추출 — 인덱스 리스트로 원하는 순서대로 선택
- 차원별 좌표 추출 — 각 차원의 인덱스를 리스트로 매칭
- pandas 계승 — iloc이 이 개념을 상속함
8. 배열 함수
8.1 메타 정보 및 변형
arr.copy() # 깊은 카피
# 메타 정보 확인
arr.shape, arr.dtype, arr.ndim
# 축 변환
arr.T, arr.T.shape # 전치
arr.transpose((1, 0)) # 차원 인덱스 지정
# 차원 변환
arr = arr.reshape((2, 2, 8))
arr.transpose((1, 2, 0)) # 다차원 축 변경
- shape / dtype / ndim — 메모리 로드 후 가장 먼저 파악할 메타 정보
- T / transpose — 차원 위치 인덱스로 변경 가능
- 활용 — 각종 알고리즘에서 요구하는 행렬 형태로 정렬
8.2 유니버설 함수
np.sum(arr), arr.sum()
np.mean(arr), arr.mean()
- 두 가지 호출 방식 — 함수형(np.sum(arr))과 메서드형(arr.sum()) 모두 지원
요약
| 개념 | 핵심 |
| ndarray | numpy의 핵심 자료구조. 동일 타입의 n차원 배열 |
| array() / asarray() | 원본 데이터로부터 배열 생성. asarray는 깊은 카피 |
| arange() / reshape() | 연속 수 생성 + 차원 조정. -1로 자동 계산 가능 |
| zeros/ones/empty | shape만 부여하고 값 채운 배열. 버퍼 용도 |
| random.randn | 정규분포 난수. DL 파라미터 초기화에 활용 |
| 브로드캐스팅 | shape이 다른 배열 연산 시 차원 자동 확장 |
| dtype / astype | 메모리 효율과 형변환 시 정보 손실 고려 |
| 슬라이싱 | 차원 유지. 일괄 변경 패턴에 적합 |
| 불리언 인덱싱 | 조건 기반 필터링. 가장 빈번한 추출 패턴 |
| 팬시 인덱싱 | 위치 직접 지정. pandas iloc의 원형 |
numpy는 ndarray 중심의 수치 계산 라이브러리로, 차원/타입/인덱싱 개념을 기반으로 pandas·polars·spark 등 상위 도구로 확장되는 데이터 분석의 근간.
'SK플래닛 ai활용 데이터엔지니어 과정 2기 > 데이터 처리' 카테고리의 다른 글
| 데이터 처리 6 - EMR + Spark (0) | 2026.05.19 |
|---|---|
| 데이터 처리 5 - Docker Spark (0) | 2026.05.19 |
| 데이터 처리 4 - Apache Spark (0) | 2026.05.18 |
| 데이터 처리 3 - polars (1) | 2026.05.14 |
| 데이터 처리 2 - pandas (0) | 2026.05.13 |