포스트

[Python 100일 챌린지] Day 61 - NumPy 기초

[Python 100일 챌린지] Day 61 - NumPy 기초

데이터 분석의 시작, NumPy! 📊

엑셀로 1만 행 데이터 처리하면 느리고 힘들죠? NumPy를 쓰면 100만 행도 1초에 처리할 수 있어요! Python 데이터 분석의 기초 중의 기초, 오늘부터 시작합니다! 💪

(25분 완독 ⭐⭐)

🎯 오늘의 학습 목표

📚 사전 지식


🎯 학습 목표 1: NumPy가 무엇인지 이해하기

한 줄 설명

NumPy = 빠른 숫자 계산을 위한 Python 라이브러리

1.1 NumPy가 필요한 이유

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# ❌ 순수 Python 리스트로 100만 개 숫자 더하기
import time

python_list = list(range(1000000))

start = time.time()
result = [x * 2 for x in python_list]
print(f"Python 리스트: {time.time() - start:.4f}")

# ✅ NumPy로 100만 개 숫자 더하기
import numpy as np

numpy_array = np.array(range(1000000))

start = time.time()
result = numpy_array * 2
print(f"NumPy 배열: {time.time() - start:.4f}")

# 출력 예시:
# Python 리스트: 0.0823초
# NumPy 배열: 0.0012초  ← 약 70배 빠름!

💡 왜 빠를까? NumPy는 C언어로 만들어져서 메모리를 효율적으로 사용하고, 벡터 연산을 지원해요!

1.2 NumPy 설치하기

1
2
# NumPy 설치
pip install numpy

설치 확인:

1
python -c "import numpy as np; print(f'NumPy {np.__version__} 설치 완료!')"

1.3 NumPy 임포트하기

1
2
3
import numpy as np  # np로 줄여서 사용하는 것이 관례!

print(np.__version__)  # 버전 확인

💡 왜 np? numpy를 매번 치기 귀찮으니까 np로 줄여요. 전 세계 개발자들이 이렇게 써요!


🎯 학습 목표 2: NumPy 배열 만들기

2.1 리스트에서 배열 만들기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import numpy as np

# 1차원 배열
arr1 = np.array([1, 2, 3, 4, 5])
print(arr1)        # [1 2 3 4 5]
print(type(arr1))  # <class 'numpy.ndarray'>

# 2차원 배열 (행렬)
arr2 = np.array([[1, 2, 3],
                 [4, 5, 6]])
print(arr2)
# [[1 2 3]
#  [4 5 6]]

# 3차원 배열
arr3 = np.array([[[1, 2], [3, 4]],
                 [[5, 6], [7, 8]]])
print(arr3.shape)  # (2, 2, 2)

2.2 특별한 배열 만들기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import numpy as np

# 0으로 채운 배열
zeros = np.zeros((3, 4))  # 3행 4열
print(zeros)
# [[0. 0. 0. 0.]
#  [0. 0. 0. 0.]
#  [0. 0. 0. 0.]]

# 1로 채운 배열
ones = np.ones((2, 3))  # 2행 3열
print(ones)
# [[1. 1. 1.]
#  [1. 1. 1.]]

# 특정 값으로 채운 배열
full = np.full((2, 2), 7)  # 7로 채움
print(full)
# [[7 7]
#  [7 7]]

# 단위 행렬 (대각선이 1)
eye = np.eye(3)
print(eye)
# [[1. 0. 0.]
#  [0. 1. 0.]
#  [0. 0. 1.]]

2.3 연속된 숫자 배열 만들기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import numpy as np

# arange: range()와 비슷
arr1 = np.arange(10)           # 0~9
print(arr1)  # [0 1 2 3 4 5 6 7 8 9]

arr2 = np.arange(1, 10, 2)     # 1부터 10 미만, 2씩 증가
print(arr2)  # [1 3 5 7 9]

# linspace: 균등 간격으로 나누기
arr3 = np.linspace(0, 1, 5)    # 0~1을 5등분
print(arr3)  # [0.   0.25 0.5  0.75 1.  ]

arr4 = np.linspace(0, 100, 11) # 0~100을 11개로
print(arr4)  # [  0.  10.  20.  30.  40.  50.  60.  70.  80.  90. 100.]

2.4 랜덤 배열 만들기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import numpy as np

# 0~1 사이 랜덤 실수
rand = np.random.rand(3, 2)  # 3x2 배열
print(rand)

# 정수 랜덤
randint = np.random.randint(1, 10, size=(2, 3))  # 1~9 사이 정수
print(randint)

# 정규분포 랜덤
randn = np.random.randn(3)  # 평균 0, 표준편차 1
print(randn)

# 시드 고정 (재현 가능한 랜덤)
np.random.seed(42)
print(np.random.rand(3))  # 항상 같은 결과!

🎯 학습 목표 3: 배열의 기본 연산 익히기

3.1 산술 연산 (벡터 연산)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import numpy as np

a = np.array([1, 2, 3, 4])
b = np.array([10, 20, 30, 40])

# 기본 연산 - 원소별로 적용!
print(a + b)   # [11 22 33 44]
print(a - b)   # [ -9 -18 -27 -36]
print(a * b)   # [ 10  40  90 160]
print(a / b)   # [0.1 0.1 0.1 0.1]
print(a ** 2)  # [ 1  4  9 16]

# 스칼라 연산
print(a + 10)  # [11 12 13 14]
print(a * 2)   # [2 4 6 8]

💡 벡터 연산: for문 없이 배열 전체에 연산이 적용돼요. 이게 NumPy의 핵심!

3.2 비교 연산

1
2
3
4
5
6
7
8
9
10
import numpy as np

arr = np.array([1, 2, 3, 4, 5])

print(arr > 3)   # [False False False  True  True]
print(arr == 3)  # [False False  True False False]
print(arr <= 2)  # [ True  True False False False]

# 조건으로 필터링
print(arr[arr > 3])  # [4 5]

3.3 집계 함수

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import numpy as np

arr = np.array([1, 2, 3, 4, 5])

print(np.sum(arr))   # 15 (합계)
print(np.mean(arr))  # 3.0 (평균)
print(np.std(arr))   # 1.414... (표준편차)
print(np.min(arr))   # 1 (최솟값)
print(np.max(arr))   # 5 (최댓값)

# 2차원 배열에서
arr2 = np.array([[1, 2, 3],
                 [4, 5, 6]])

print(np.sum(arr2))          # 21 (전체 합)
print(np.sum(arr2, axis=0))  # [5 7 9] (열 합)
print(np.sum(arr2, axis=1))  # [6 15] (행 합)

💡 axis 이해하기: axis=0은 행 방향(↓), axis=1은 열 방향(→)

3.4 수학 함수

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import numpy as np

arr = np.array([1, 4, 9, 16])

print(np.sqrt(arr))   # [1. 2. 3. 4.] 제곱근
print(np.exp(arr))    # 지수 함수
print(np.log(arr))    # 자연로그

# 삼각함수
angles = np.array([0, np.pi/2, np.pi])
print(np.sin(angles))  # [0. 1. 0.]

# 반올림
arr2 = np.array([1.2, 2.5, 3.7])
print(np.round(arr2))  # [1. 2. 4.]
print(np.floor(arr2))  # [1. 2. 3.] 내림
print(np.ceil(arr2))   # [2. 3. 4.] 올림

🎯 학습 목표 4: 배열의 속성과 형태 다루기

4.1 배열 속성 확인하기

1
2
3
4
5
6
7
8
9
import numpy as np

arr = np.array([[1, 2, 3],
                [4, 5, 6]])

print(arr.shape)   # (2, 3) - 형태 (2행 3열)
print(arr.ndim)    # 2 - 차원 수
print(arr.size)    # 6 - 총 원소 개수
print(arr.dtype)   # int64 - 데이터 타입

4.2 배열 형태 바꾸기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import numpy as np

arr = np.arange(12)  # [0, 1, 2, ..., 11]

# reshape: 형태 변경
arr2d = arr.reshape(3, 4)  # 3행 4열로
print(arr2d)
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]

arr3d = arr.reshape(2, 2, 3)  # 2x2x3으로
print(arr3d.shape)  # (2, 2, 3)

# -1 사용: 자동 계산
arr_auto = arr.reshape(4, -1)  # 4행, 열은 자동
print(arr_auto.shape)  # (4, 3)

# flatten: 1차원으로 펼치기
flat = arr2d.flatten()
print(flat)  # [ 0  1  2  3  4  5  6  7  8  9 10 11]

4.3 데이터 타입 변환

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import numpy as np

# 정수 배열
arr_int = np.array([1, 2, 3])
print(arr_int.dtype)  # int64

# 실수로 변환
arr_float = arr_int.astype(float)
print(arr_float)        # [1. 2. 3.]
print(arr_float.dtype)  # float64

# 문자열로 변환
arr_str = arr_int.astype(str)
print(arr_str)  # ['1' '2' '3']

4.4 배열 합치기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import numpy as np

a = np.array([1, 2, 3])
b = np.array([4, 5, 6])

# 1차원 합치기
print(np.concatenate([a, b]))  # [1 2 3 4 5 6]

# 2차원 합치기
c = np.array([[1, 2], [3, 4]])
d = np.array([[5, 6], [7, 8]])

# 세로로 합치기 (axis=0)
print(np.vstack([c, d]))
# [[1 2]
#  [3 4]
#  [5 6]
#  [7 8]]

# 가로로 합치기 (axis=1)
print(np.hstack([c, d]))
# [[1 2 5 6]
#  [3 4 7 8]]

💡 실전 팁 & 주의사항

✅ 좋은 습관

1
2
3
4
5
6
7
8
9
10
11
12
import numpy as np

# 1. 항상 np로 임포트
import numpy as np  # ✅ 권장
# import numpy     # ❌ 비권장

# 2. 배열 생성 시 dtype 명시
arr = np.array([1, 2, 3], dtype=np.float64)

# 3. 복사본 만들기 (원본 보호)
original = np.array([1, 2, 3])
copy = original.copy()  # ✅ 독립적인 복사본

⚠️ 주의사항

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import numpy as np

# 뷰(view) vs 복사(copy)
arr = np.array([1, 2, 3, 4, 5])

# 슬라이싱은 뷰를 반환 (원본 공유!)
view = arr[1:4]
view[0] = 100
print(arr)  # [  1 100   3   4   5] ← 원본도 변경됨!

# 복사본을 원하면 .copy() 사용
arr = np.array([1, 2, 3, 4, 5])
copy = arr[1:4].copy()
copy[0] = 100
print(arr)  # [1 2 3 4 5] ← 원본 유지!

🧪 연습 문제

문제 1: 성적 분석하기

학생 5명의 국어, 영어, 수학 점수가 있습니다. 각 과목별 평균과 학생별 총점을 구하세요.

1
2
3
4
5
6
7
8
scores = np.array([
    [85, 90, 88],   # 학생1
    [78, 82, 80],   # 학생2
    [92, 88, 95],   # 학생3
    [65, 70, 72],   # 학생4
    [88, 85, 90]    # 학생5
])
# 과목별 평균? 학생별 총점?
💡 힌트
  • np.mean(scores, axis=0) → 열(과목)별 평균
  • np.sum(scores, axis=1) → 행(학생)별 합계
정답 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import numpy as np

scores = np.array([
    [85, 90, 88],
    [78, 82, 80],
    [92, 88, 95],
    [65, 70, 72],
    [88, 85, 90]
])

# 과목별 평균 (axis=0: 열 방향)
subject_avg = np.mean(scores, axis=0)
print(f"국어 평균: {subject_avg[0]:.1f}")
print(f"영어 평균: {subject_avg[1]:.1f}")
print(f"수학 평균: {subject_avg[2]:.1f}")

# 학생별 총점 (axis=1: 행 방향)
student_total = np.sum(scores, axis=1)
for i, total in enumerate(student_total, 1):
    print(f"학생{i} 총점: {total}")

문제 2: 조건 필터링

1부터 100까지의 숫자 중에서 3의 배수이면서 5의 배수가 아닌 숫자들의 합을 구하세요.

💡 힌트
  • np.arange(1, 101)로 배열 생성
  • (arr % 3 == 0) & (arr % 5 != 0) 조건 사용
  • 조건으로 필터링 후 np.sum() 적용
정답 코드
1
2
3
4
5
6
7
8
9
10
11
import numpy as np

arr = np.arange(1, 101)

# 조건: 3의 배수이면서 5의 배수가 아닌 것
condition = (arr % 3 == 0) & (arr % 5 != 0)

# 조건에 맞는 숫자들
filtered = arr[condition]
print(f"해당 숫자들: {filtered}")
print(f"합계: {np.sum(filtered)}")

📝 오늘 배운 내용 정리

  1. NumPy = 빠른 숫자 계산 라이브러리 (Python 리스트보다 수십 배 빠름)
  2. 배열 생성: np.array(), np.zeros(), np.ones(), np.arange(), np.linspace()
  3. 벡터 연산: for문 없이 배열 전체에 연산 적용
  4. 집계 함수: sum(), mean(), std(), min(), max()
  5. 배열 형태: shape, reshape(), flatten()

🔗 관련 자료


📚 이전 학습

Day 60: 미니 프로젝트: 뉴스 스크래퍼 ⭐⭐⭐

어제는 Phase 6 마무리로 웹 스크래핑 프로젝트를 완성했어요!

📚 다음 학습

Day 62: NumPy 활용 ⭐⭐

내일은 배열 인덱싱, 슬라이싱, 브로드캐스팅 등 NumPy 심화 내용을 배워요!


“데이터 분석의 첫 걸음, NumPy로 시작합니다!” 📊

Day 61/100 Phase 7: 데이터 분석 기초 #100DaysOfPython
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.