데이터 분석의 시작, 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)}")
|
📝 오늘 배운 내용 정리
- NumPy = 빠른 숫자 계산 라이브러리 (Python 리스트보다 수십 배 빠름)
- 배열 생성:
np.array(), np.zeros(), np.ones(), np.arange(), np.linspace() - 벡터 연산: for문 없이 배열 전체에 연산 적용
- 집계 함수:
sum(), mean(), std(), min(), max() - 배열 형태:
shape, reshape(), flatten()
🔗 관련 자료
📚 이전 학습
Day 60: 미니 프로젝트: 뉴스 스크래퍼 ⭐⭐⭐
어제는 Phase 6 마무리로 웹 스크래핑 프로젝트를 완성했어요!
📚 다음 학습
Day 62: NumPy 활용 ⭐⭐
내일은 배열 인덱싱, 슬라이싱, 브로드캐스팅 등 NumPy 심화 내용을 배워요!
“데이터 분석의 첫 걸음, NumPy로 시작합니다!” 📊
| Day 61/100 | Phase 7: 데이터 분석 기초 | #100DaysOfPython |