NumPy 사용해보기
10 Jul 2025 | DA개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.
NumPy
NumPy는 Python에서 과학 연산을 위해 사용하는 가장 기본적인 패키지 중 하나라고 한다. 다차원 배열과 행렬 연산에 필요한 다양한 함수와 메소드를 제공한다.
NumPy 설지
pip install NumPy
# 다 설치되고나면
import numpy as np # import 해주고
np.__version__ # 버전 확인
NumPy 배열 생성
NumPy에서 가장 기본적인 데이터 구조는 배열이다. NumPy 배열은 동일한 타입의 데이터를 담는 다차원 배열로 ndarray
클래스를 사용해 생성할 수 있다.
import numpy as np
# 1차원 배열 생성
a = np.array([1,2,3])
# 2차원 배열 생성
b = np.array([[1,2,3], [4,5,6]])
# 3차원 배열 생성
c = np.array([[[1,2], [3,4]], [[1,2], [3,4]]])
ndim
배열의 차원(Dimension)을 알기 위한 함수
a.ndim # > 결과값: 1
b.ndim # > 결과값: 2
c.ndim # > 결과값: 3
shape
배열의 크기(Shape)를 확인
a.shape # 결과값: (3,)
b.shape # 결과값: (2,3)
c.shape # 결과값: (2,2,2)
size
배열에 있는 총 원소의 개수
a = np.array([1,2,3])
a.size # > 3
배열 연산
NumPy 배열은 다른 배열 또는 스칼라와의 연산을 지원한다.
스칼라: 스칼라의 어원은 라틴어 scala에서 왔다고 하며 이는 “저울” 이란 뜻이라고 한다. 즉, 어떤 양(크기)을 나타내는 개념인 것이다. 선형대수학에서의 스칼라의 정의 또한 “벡터 공간에서 벡터를 곱할 수 있는 양”이다. 쉽게 생각해서 실수가 선형대수학에선 스칼라인 것이다.
스칼라에 대해 찾아봤는데, 이 말이 그나마 제일 이해하기 쉬웠던 것 같다.(문과생 웁니다..)
결국 스칼라는 실수라는건데.. 실수는 유리수와 무리수 모든것을 말하는거니.. 이쯤..이해하고..일단 패스..
a = np.array([1,2,3])
b = np.array([4,5,6])
# 덧셋
c = a + b # > [5,7,9]
# 곱셈
d = a * b # > [4,10,18]
# 스칼라와 연산
e = a + 1 # > [2,3,4]
추가로 NumPy 배열 연산 안에는 sum
, mean
, min
, max
등로 지원해준다.
a = np.array([1,2,3])
# 합
b = np.sum(a) # > 6
# 평균
c = np.mean(a) # > 2.0
# 최소값
d = np.min(a) # > 1
# 최대값
e = np.max(a) # > 3
### 배열 인덱싱과 슬라이싱
a = np.array([1,2,3,4,5])
# 인뎅싱
b = a[0] # > 1
c = a[3] # > 4
# 슬라이싱
d = a[1:4] # > [2,3,4]
e = a[:3] # > [1,2,3]
f = a[1:] # > [2,3,4,5]
NumPy 에서는 다차원 배열에서의 인덱싱, 슬라이싱 또한 가능하다.
a = np.array([[1,2,3], [4,5,6]])
# 위 배열의 출력값은 아래처럼 나온다
# array([[1,2,3]
# [4,5,6]])
# 인덱싱
b = a[0, 0] # 1
c = a[1, 2] # 6
# 슬라이싱
d = a[0, 1:3] # [2, 3]
e = a[:, 1] # [2, 5]
f = a[:, :2] # [[1, 2], [4, 5]]
(다차원 배열에서의 슬라이싱이 좀 어렵다.. 이해는 간다만..ㅎ 버퍼링이 좀 생김ㅎㅋ)
arange (start, stop, step)
정해진 step만큼 일정하게 떨어진 숫자를 배열로 반환
start의 기본값은 0, step의 기본값은 1로 직접 지정해주지 않으면 기본값을 행한다. stop 값은 반드시 전달되어야 한다!
np.arange[3] # > [0,1,2]
np.arange[1,10,2] # > [1,3,5,7,9]
dot
배열간의 행렬 곱셈을 배열로 반환
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
np.dot(a,b)
# array[[19 22]
# [43 50]]
이때 궁금증은 *
연산자와의 차이는 무엇일까?
dot
은 배열간의 행렬 곱셈을 한다면*
은 요소별 곱셈을 한다.
위에서 다룬 dot의 경우 행해진 곱셈 연산은 아래와 같다.
# [[1*5 + 2*7, 1*6 + 2*8]
# [3*5 + 4*7, 3*6+ 4*8]]
그치만 *은 아래와 같다
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
a * b
# array[[ 5 12]
# [21 32]]
reshape
NumPy 배열의 형태를 변경
reshape을 사용하기 위해서는 기존 배열과 변환 후 배열의 원소개수가 동일해야한다. 즉 (2,4)와 (4,2)의 reshape은 가능하다. reshape 메서드를 사용하는 주 목적이 차원을 유지한 상태에서 배열의 형태를 변환하는 것이라고 한다.
# a라는 np array 생성 > 2차원 배열
a = np.array([[1, 2], [3, 4], [5, 6]])
# array([[1, 2],
# [3, 4],
# [5, 6]])
a.shape # > (3,2)
a.ndim # > 2
b = a.reshape(2,3)
# array([[1, 2, 3],
# [4, 5, 6]])
b.shape # > (2,3)
b.ndim # > 2
tranpose
NumPy 배열의 차원을 변경하여 전치된 배열을 반환
전치: 행렬을 대각선으로 뒤집는 연산자..(뭔..)로 행렬의 행과 열 인덱스를 바꾸어 다른 행렬을 생성하는 것을 의미한다.
설명이 어려우니.. 코드로 확인해보자!
original_array = np.array([[1, 2, 3], [4, 5, 6], 7, 8, 9]])
# array([[1, 2, 3],
# [4, 5, 6],
# [7, 8, 9]])
transposed_array = np.transpose(original_array)
# array([[1, 4, 7],
# [2, 5, 8],
# [3, 6, 9]])
직접 찍어보니 알 것 같다! 행과 열을 바꾼다라는 개념..!
중요한 포인트는 tranpose 또한 reshape과 같이 배열 요소 개수가 같아야하는 것은 동일하다! 즉 2x3 배열을 전치해서 3x2 배열을 반환하는 것!
zeros, ones
- zeros: 모든 원소가 0인 배열을 생성
- ones: 모든 원소가 1인 배열을 생성
a = np.zeros((2,3))
# array[[0. 0. 0.]
# [0. 0. 0]]
b = np.ones((2,3))
# array[[1. 1. 1.]
# [1. 1. 1.]]
where
where은 조건에 부합하는 인덱스를 반환해주는 함수
예시를 들자면
a = np.arange(5,15)
# array([5,6,7,8,9,10,11,12,13,14])
np.where(a > 10)
# 11~14까지의 인덱스를 반환
# array([6,7,8,9]) > 인덱스를 반환해준거임!!
linspace
지정해준 범위 내에서 균등한 간격으로 원하는 개수의 배열을 생성
a = np.linspace(0,1,5) # [0. 0.25 0.5 0.75 1. ]
random.random
0과 1사이의 균등분포에서 난수를 생성해 배열을 만듦. 함수의 인수로 생성할 배열의 크기를 지정 가능.
a = np.random.random(3,3)
#array([[0.5254058 , 0.39879012, 0.61469921],
# [0.72924439, 0.10349449, 0.84673281],
# [0.61774079, 0.71552584, 0.50629848]])
random.randn
평균이 0이고 표준편차가 1인 정규분포를 따르는 난수를 생성해 배열을 만듦. 함수의 인수로 생성할 배열의 크기를 지정 가능.
a = np.random.randn(3,3)
# array([[-1.90644415, 1.58210398, -2.03024185],
# [ 0.07563648, 0.10644284, -0.73066284],
# [ 0.07573001, 0.19376196, -1.18768222]])
정규분포, 표준편차.. 다 까먹었다. 나중에 따로 공부해서 정리해야겠다.
Numpy 난수 함수
난수: 정의된 범위 내에서 무작위로 추출된 수
- seed() : 난수 발생기의 seed를 지정
- shuffle() : 리스트나 배열의 순서를 뒤섞음
- choice(): 배열에서 무작위로 추출
- rand() : 균등분포에서 표본을 추출
- randint() : 주어진 최소/최대 범위 안에서 임의의 난수를 추출
- randn() : 표준편차가 1이고 평균값이 0인 정규분포에서 표본을 추출
- normal() : 정규분포(가우시안)에서 표본을 추출
randn 과 normal?
두 함수 모두 정규분포에서 난수를 생성한다는 공통점이 있지만 약간의 차이점도 존재한다.
- randn(): 표준편차가 1이고 평균이 0인 표준정규분호에서 난수 생성
- normal(): 평균값과 표준편차를 직접 지정할 수 있음
따라서 randm()
함수는 normal(0,1)
과 동일한 역할을 한다!
주요 유니버설 함수
- sqrt(): 제곱근
- log(): 자연로그
- greater_equal(): 비교
- logical_and(): 논리