반응형
-
🐍 [파이썬 데이터 분석] NumPy(넘파이) 완벽 정복 1편: 배열의 탄생과 차원의 이해
파이썬으로 데이터 분석이나 인공지능을 시작하면 가장 먼저 마주치는 라이브러리, 바로 NumPy(넘파이)입니다. "그냥 파이썬 리스트(list)를 쓰면 안 되나요?"라고 물으실 수 있습니다. 하지만 데이터가 수백만 개로 늘어나면 파이썬 리스트는 너무 느려집니다. 넘파이는 C언어 기반으로 만들어져 데이터를 메모리에 연속적으로 배치하기 때문에 압도적인 연산 속도를 자랑합니다.
🧱 1. 넘파이 데이터 구조와 필수 용어 (차원의 이해)- 스칼라 (Scalar, 0차원): 숫자 단 1개 (예: 5)
- 벡터 (Vector, 1차원): 숫자가 한 줄로 나열된 기차 (예: [1, 2, 3])
- 행렬 (Matrix, 2차원): 행(Row)과 열(Column)로 이루어진 엑셀 표 (예: [[1, 2], [3, 4]])
- 텐서 (Tensor, 3차원 이상): 행렬이 여러 개 겹쳐진 큐브 형태 (예: 컬러 이미지 데이터)
- arr.ndim: 배열의 차원 수 (예: 1, 2, 3)
- arr.shape: 배열의 모양/형태 (예: (3, 4) = 3행 4열)
- arr.size: 배열 안의 전체 원소 개수 (예: 12개)
- arr.dtype: 배열 안 데이터의 자료형 (예: int32, float64)
🛠️ 2. 다양한 배열 생성 함수 (Array Creation)① 특정 값으로 채우기- np.zeros(shape): 모든 값을 0으로 채웁니다. (초기화할 때 가장 많이 씁니다.)
- 예: np.zeros((2, 3)) ➡️ 2행 3열짜리 0 행렬 생성
- np.ones(shape): 모든 값을 1로 채웁니다.
- np.full(shape, fill_value): 내가 원하는 특정 숫자로 꽉 채웁니다.
- 예: np.full((3, 3), 7) ➡️ 7로 꽉 찬 3x3 배열
- np.eye(N): 대각선만 1이고 나머지는 0인 단위 행렬(Identity Matrix)을 만듭니다. (선형대수 연산 시 필수!)
- np.zeros_like(A): A와 모양이 같은 0 행렬
- np.ones_like(A): A와 모양이 같은 1 행렬
- np.full_like(A, 5): A와 모양이 같고 5로 채워진 행렬
📏 3. 규칙적인 연속된 숫자 만들기- np.arange(start, stop, step)
- 파이썬의 range와 똑같습니다. "간격(step)"이 중요할 때 씁니다.
- np.arange(1, 10, 2) ➡️ [1, 3, 5, 7, 9] (1부터 10 전까지 2씩 띄어서!)
- np.linspace(start, stop, num)
- "개수(num)"가 중요할 때 씁니다. 지정한 개수만큼 구간을 아주 공평하게 쪼개줍니다.
- np.linspace(0, 100, 5) ➡️ [0, 25, 50, 75, 100] (0부터 100까지 정확히 5등분!)
🎲 4. 무작위 난수 생성하기 (Random)- np.random.seed(42) (중요 🌟)
- 컴퓨터의 난수는 사실 완벽한 무작위가 아니라 공식에 의해 나옵니다. 시드(Seed) 번호를 고정해두면, 언제 어디서 코드를 실행하든 항상 똑같은 난수가 나옵니다. (실험 재현성을 위해 필수!)
- np.random.rand(): 0 ~ 1 사이의 균등 분포 난수 생성
- np.random.randn(): 평균 0, 표준편차 1인 표준 정규 분포(가우시안) 난수 생성
- np.random.randint(low, high, size): 지정한 범위 내의 정수 난수 생성
- 예: np.random.randint(1, 100, size=(3,3)) ➡️ 1~99 사이의 정수로 3x3 배열 생성
- np.random.choice(a, size, replace): 주어진 데이터 안에서 무작위로 샘플링(뽑기) 합니다. (replace=False를 주면 중복 없이 뽑는 로또 추첨기가 됩니다!)
🔄 5. 데이터 타입 변경하기 (astype)Pythonimport numpy as np # 기본적으로 정수를 넣으면 int32 또는 int64로 만들어집니다. arr = np.array([1, 2, 3, 4]) # 실수형(float32)으로 강제 변환! arr_float = arr.astype('float32') print(arr_float) # 결과: [1., 2., 3., 4.] - 넘파이 배열은 무조건 '단일 데이터 타입'만 가질 수 있습니다. (정수면 정수, 실수면 실수) 만약 배열을 만들었는데 용량을 너무 많이 차지해서 크기를 줄이고 싶거나, 정수를 실수로 바꿔야 한다면 astype()을 사용합니다.
- 인공지능 모델의 가중치를 초기화하거나 테스트 데이터를 만들 때 무작위 숫자(난수)가 필요합니다.
- 반복문(for문)을 돌리거나 그래프의 X축을 만들 때 필수적인 함수들입니다. 두 함수의 차이를 꼭 기억하세요!
- 실무에서 진짜 많이 쓰는 함수입니다. 기존에 있던 배열 A와 크기(Shape)는 똑같게 유지하면서 안의 내용물만 0이나 1로 싹 비우고 싶을 때 사용합니다.
- 가장 기본적으로는 np.array([1, 2, 3])처럼 기존 파이썬 리스트를 넘파이 배열로 바꿀 수 있습니다. 하지만 넘파이는 원하는 크기의 배열을 뚝딱 만들어주는 마법 같은 함수들을 제공합니다.
- 넘파이 배열을 만들었다면, 이 배열의 '호구조사'를 할 수 있어야 합니다.
- 넘파이는 데이터를 ndarray (N-dimensional Array, 다차원 배열) 라는 구조로 관리합니다. 차원(Dimension)이 커질수록 데이터를 부르는 이름이 다릅니다.
🔎 [파이썬 데이터 분석] 교재에 숨어있던 넘파이(Numpy) 심화 디테일 4가지
🛠️ 1. 데이터의 성질을 지배하라! (dtype과 astype)
파이썬 기본 리스트는 하나의 리스트 안에 숫자, 문자 등 다양한 것을 섞어 넣을 수 있지만, 넘파이 배열은 무조건 '단일 데이터 타입'만 가질 수 있습니다. 이것이 넘파이가 계산 속도를 극한으로 끌어올리는 비결입니다.
- a.dtype: 배열 안의 데이터가 어떤 타입인지(정수형 int, 실수형 float, 문자열 등) 확인합니다.
- a.astype('float32'): 배열의 데이터 타입을 강제로 바꿉니다.
- 💡 실무 꿀팁: 인공지능(딥러닝) 모델에 데이터를 넣을 때는 메모리를 아끼기 위해 64비트 정수형(int64)을 32비트 실수형(float32)으로 바꾸는 astype 작업이 아주 빈번하게 일어납니다!
📏 2. 더 다양한 배열 생성의 마법사들 (linspace와 _like)
arange나 zeros 외에도 교재에 소개된 아주 유용한 생성 함수들이 있습니다.
- np.linspace(0, 10, 5): 0부터 10까지를 정확히 5개의 구간으로 일정하게 쪼개서 배열을 만듭니다. (결과: [0., 2.5, 5., 7.5, 10.]) 그래프의 X축을 촘촘하게 그릴 때 필수입니다!
- np.ones((2, 3)): zeros가 0으로 채운다면, 이건 1로 꽉 찬 2행 3열 배열을 만듭니다.
- np.zeros_like(a): 기존에 만들어둔 배열 a와 껍데기(모양과 크기)는 똑같이 유지한 채로, 알맹이만 전부 0으로 비워서 새로운 배열을 만듭니다. (진짜 많이 씁니다!)
✨ 3. 넘파이 연산의 진짜 마법: 브로드캐스팅 (Broadcasting)
지난번에 '벡터화 연산(배열끼리의 계산)'을 말씀드렸죠? 이때 아주 중요한 규칙이 교재에 숨어 있습니다. 원래 수학적으로 행렬끼리 더하거나 곱하려면 '두 배열의 모양(shape)'이 완전히 똑같아야 합니다. 하지만 넘파이는 똑똑하게도 모양이 달라도 알아서 크기를 쭉쭉 늘려서(복사해서) 계산을 맞춰줍니다. 이것을 브로드캐스팅이라고 합니다.
- 원리: [1, 2, 3] 이라는 1차원 배열에 그냥 숫자 10을 더하면? 넘파이가 속으로 숫자 10을 [10, 10, 10]으로 쭉 늘린 다음 계산해서 [11, 12, 13]을 뱉어냅니다.
- 2차원 표(행렬)에 1차원 줄(벡터)을 더할 때도, 줄을 여러 개로 복사해서 표의 크기와 맞춘 뒤 계산해 버리는 엄청난 기능입니다.
💾 4. 메모리 폭발을 막아라: 복사본(Copy) vs 원본 바라보기(View)
이 부분은 교재의 '배열 형태 변경' 파트에 아주 살짝 숨어있는 고수들의 영역입니다. 2차원 표를 1차원 한 줄로 쫙 펴는 함수는 2가지가 있습니다. 결과는 똑같아 보이지만 내부 작동은 완전히 다릅니다.
- a.flatten() (Copy): 원본은 그대로 두고, 완전히 새로운 배열(복사본)을 만들어서 폅니다. 이걸 수정해도 원본 a는 안전합니다. (메모리는 더 먹습니다)
- a.ravel() (View): 새로운 걸 만들지 않고, 원본 a를 그냥 보는 각도만 1차원으로 눕혀서 보여줍니다. 만약 이 값을 수정하면 원본 a의 값도 같이 바뀌어 버립니다! (메모리는 아낄 수 있습니다)
- 인덱싱의 차이: 일반적인 슬라이싱(a[1:3])은 View(원본 연동)를 반환하지만, 팬시/불리언 인덱싱(a[a>10])은 Copy(독립된 복사본)를 반환합니다.
📝 [실습 TODO] 내 손으로 넘파이 직접 다뤄보기!
아래 미션을 보고 주피터 노트북 빈 셀에 직접 코드를 작성해 보세요! 머리로 아는 것보다 손으로 쳐보는 게 10배 빨리 늘어납니다.
- TODO 1 (생성): np.arange를 사용하여 1부터 20까지 연속된 숫자가 들어있는 1차원 배열 arr을 생성하세요.
- TODO 2 (형태 변경): 생성한 arr을 reshape를 사용하여 4행 5열짜리 2차원 행렬 모양으로 바꾸고 변수 matrix에 저장하세요.
- TODO 3 (불리언 인덱싱): matrix 안의 숫자 중 10 이상 15 이하인 숫자들만 골라내어 출력해 보세요. (조건은 괄호로 묶고 & 기호를 사용하세요!)
- TODO 4 (벡터 연산 & 통계): matrix의 모든 숫자에 10을 곱한 뒤, 그 결과 배열에 들어있는 모든 원소의 합(sum)을 구해서 출력하세요.
💡 [정답 확인란]
직접 코딩을 마친 후 아래 코드를 드래그하여 확인해 보세요!
Python
import numpy as np
# [TODO 1] 1부터 20까지 배열 생성 (끝 번호는 포함 안 되므로 21로 작성)
arr = np.arange(1, 21)
# [TODO 2] 4행 5열로 모양 변경
matrix = arr.reshape(4, 5)
# [TODO 3] 10 이상 15 이하 조건 필터링
result_bool = matrix[(matrix >= 10) & (matrix <= 15)]
print("10 이상 15 이하인 값:", result_bool)
# [TODO 4] 모든 원소에 10 곱하고 전체 합계 구하기
result_sum = (matrix * 10).sum()
print("모든 원소에 10을 곱한 후의 총합:", result_sum)
반응형
'두두 IT > 파이썬' 카테고리의 다른 글
| [머신런닝 2] 머신러닝 분석 - Iris_분석 (0) | 2026.05.12 |
|---|---|
| [PYTHON] NumPy 데이터 다루기 (0) | 2026.05.08 |
| [PYTHON] 시각화 3가지 방식 비교 (1) | 2026.05.08 |
| [PYTHON 시각화] Pandas 내장 시각화 (0) | 2026.05.07 |
| [PYTHON 시각화] Matplotlib 주요그래프 (1) | 2026.05.07 |