NumPy 기반 데이터 분석 핵심 기술

NumPy는 고성능 다차원 배열 객체와 이를 활용한 수치 계산을 위한 핵심 라이브러리로, 데이터 과학 및 분석 작업의 기반이 됩니다. 주로 2차원 형태의 업무 데이터를 처리하는 데 최적화되어 있으며, 다음과 같이 임포트하여 사용합니다.

import numpy as np
print(np.__version__)

배열 생성과 데이터 형식

NumPy 배열(ndarray)은 동일한 데이터 타입을 가지는 연속적인 메모리 공간을 기반으로 하며, 이는 파이썬 내장 리스트와 구분되는 핵심 특징입니다. 리스트와 달리 모든 요소가 같은 형식이어야 하며, 혼합형 입력 시 형 변환 우선순위는 문자열 > 실수 > 정수 순입니다.

x = np.array([1, 2, 3])

배열 생성 시 다양한 옵션을 지정할 수 있습니다:

  • dtype: 원소의 데이터 타입 (예: np.float32)
  • copy: 원본 객체 복사 여부
  • order: 메모리 저장 방향 ('C': 행 우선, 'F': 열 우선)
  • ndmin: 최소 차원 수 지정

특수 배열 생성 함수

다양한 패턴의 배열을 효율적으로 생성할 수 있는 도구들이 제공됩니다.

1. 1로 채워진 배열: np.ones()

# 4행 3열의 정수 배열 생성
np.ones((4, 3), dtype=np.int8)

# 1차원 배열
np.ones(5)

2. 0으로 채워진 배열: np.zeros()

np.zeros((3, 2))

3. 특정 값으로 채우기: np.full()

np.full((2, 4), fill_value=7)

4. 단위 행렬 생성: np.eye()

# 3x3 단위 행렬
np.eye(3)

# 대각선 오프셋 적용
np.eye(4, k=1)  # 위로 한 칸 이동

5. 등간격 수열 생성

np.linspace()은 시작값, 끝값, 개수를 기준으로 균등하게 분포된 값을 생성합니다.

np.linspace(0, 10, num=5)        # [0, 2.5, 5, 7.5, 10]
np.linspace(0, 10, num=5, endpoint=False)  # [0, 2, 4, 6, 8]

np.arange()은 시작, 종료, 간격(step)을 기반으로 배열을 만듭니다.

np.arange(0, 10, 2)  # [0, 2, 4, 6, 8]

6. 난수 기반 배열

확률 분포를 활용한 배열 생성도 가능합니다.

  • 정수 난수: np.random.randint(0, 100, size=(3,3))
  • 표준 정규분포: np.random.randn(2, 4)
  • 일반 정규분포: np.random.normal(loc=175, scale=10, size=1000)
  • 0~1 사이 실수: np.random.random((2, 3))
  • 셔플 인덱스: np.random.permutation(6) → [3, 1, 5, 0, 4, 2]

배열 속성 확인

생성된 배열의 구조를 분석하기 위한 주요 속성들:

  • ndim: 차원 수 (예: 2차원 배열 → 2)
  • shape: 각 차원의 크기 튜플 (예: (3, 4))
  • size: 전체 원소 수
  • dtype: 데이터 타입
arr = np.array([[1, 2], [3, 4], [5, 6]])
print(arr.ndim)   # 2
print(arr.shape)  # (3, 2)
print(arr.size)   # 6

인덱싱과 슬라이싱

다양한 방식으로 배열의 특정 요소에 접근할 수 있습니다.

# 기본 인덱싱
data = np.array([[10, 20, 30], [40, 50, 60]])

# 전통적 접근
print(data[1][2])  # 60

# NumPy 스타일
print(data[1, 2])  # 60 (권장)

# 불리언 마스킹
mask = data > 30
print(mask)
# [[False False False]
#  [ True  True  True]]
print(data[mask])  # [40 50 60]

슬라이싱 (왼쪽 닫힘, 오른쪽 열림)

vec = np.arange(8)
print(vec[2:6])  # [2, 3, 4, 5]

mat = np.random.randint(1, 10, (4, 5))

# 행 슬라이싱
print(mat[1:3])

# 열 슬라이싱
print(mat[:, 1:3])  # 모든 행, 2~3번째 열

형태 변환: reshape()

총 원소 수가 유지되는 조건에서 배열의 형태를 재구성합니다.

a = np.arange(12)
b = a.reshape(3, 4)
print(b.shape)  # (3, 4)

배열 결합 (Concatenation)

여러 배열을 하나로 연결할 수 있습니다.

A = np.ones((2, 3))
B = np.zeros((2, 3))

# 수직 결합 (axis=0)
np.concatenate([A, B], axis=0)  # 결과: (4, 3)

# 수평 결합 (axis=1)
np.concatenate([A, B], axis=1)  # 결과: (2, 6)

단축 함수도 제공됩니다:

  • np.vstack([A, B]) → 수직 결합
  • np.hstack([A, B]) → 수평 결합

배열 분할 (Splitting)

배열을 여러 조각으로 나눌 수 있습니다.

X = np.arange(12).reshape(3, 4)

# 균등 분할
np.split(X, 2, axis=1)  # 두 개의 (3,2) 배열 반환

# 지정 위치에서 분할
np.split(X, [1, 3], axis=1)  # 세 부분으로 분할

편의 함수:

  • np.hsplit(X, 2) → 수평 분할
  • np.vsplit(X, 3) → 수직 분할

복사와 참조

기본 할당은 참조만 생성하므로, 원본 배열이 변경됩니다. 독립적인 사본을 만들려면 copy()를 사용해야 합니다.

original = np.array([1, 2, 3])
view = original       # 참조
clone = original.copy()  # 독립 복사

view[0] = 99
print(original[0])   # 99 (변경됨)
print(clone[0])      # 1 (유지됨)

태그: NumPy 데이터분석 ndarray 배열연산 파이썬

6월 7일 18:21에 게시됨