Numpy
- Numerical Python
- 수학 및 과학 연산을 위한 파이썬 패키지
- Numpy 내부는 상당부분이 C나 Fortran으로 작성되어 있어 실행 속도가 꽤 빠른 편이다.
- 기본적으로 array라는 자료를 생성하고, 이를 바탕으로 색인, 처리, 연산 등을 하는 기능을 수행한다.
- Numpy 자체만으로도 난수생성, 푸리에변환, 행렬연산, 간단한 기술통계 분석 정도는 가능하지만 실제로는 Scipy, Pandas, matplotlib 등 다른 Python 패키지와 함께 쓰이는 경우가 많다.
Numpy Data Types
Numpy Type | C Type | Description |
numpy.bool_ | bool | Boolean (True or False) stored as a byte |
numpy.byte | signed char | C와 동일 |
numpy.ubyte | unsigend char | C와 동일 |
numpy.short | short | C와 동일 |
numpy.ushort | unsigned short | C와 동일 |
numpy.intc | int | C와 동일 |
numpy.uintc | unsigned int | C와 동일 |
numpy.int_ | long | C와 동일 |
numpy.uint | unsigned long | C와 동일 |
numpy.longlong | long long | C와 동일 |
numpy.ulonglong | unsigned long long | C와 동일 |
numpy.half / numpy.float16 |
Half Precision Float: Sign bit, 5 bits Exponent(지수부), 10 bits mantissa(가수부) |
|
numpy.single | float | Single Precision Float: Sign bit, 8 bits Exponent, 23 bits mantissa |
numpy.double | double | Double Precision Float: Sign bit, 11 bits Exponent, 52 bits mantissa |
numpy.longdouble | long double | extended-precision float |
numpy.csingle | float complex | Complex number, represented by two single-precision floats (real and imaginary components) |
numpy.cdouble | double complex | Complex number, represented by two double-precision floats (real and imaginary components) |
numpy.clongdouble | long double complex | Complex number, represented by two extended-precision floats (real and imaginary components) |
Numpy Array 생성
# numpy 라이브러리 불러오기
import numpy as np
# 1차원 리스트 선언
data1 = [1, 2, 3, 4, 5, 6]
# 2차원 리스트(행렬) 선언
data2 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
# list를 numpy array로 변환
array1 = np.array(data1)
array2 = np.array(data2)
- numpy array의 원소는 모두 같은 데이터타입을 갖는다.
- 만약 1개의 원소가 float이고 나머지 원소가 int인 경우, 모든 원소는 float로 변환된다.
Numpy Array 타입, 데이터 출력
# type, data 출력
print(type(array1), '\n', array1, '\n')
print(type(array2), '\n', array2)
<class 'numpy.ndarray'>
[1 2 3 4 5 6]
<class 'numpy.ndarray'>
[[1 2 3]
[4 5 6]
[7 8 9]]
Numpy Array 차원 및 크기 출력
# array2의 차원
print("array2의 ndim : ", array2.ndim)
# array2의 행, 열의 크기
print("array2의 shape : ", array2.shape)
# array2의 크기(행 x 열)
print("array2의 size : ", array2.size)
# array2 내부 원소의 타입(Numpy Array의 모든 원소는 동일한 타입이어야 함)
print("array2의 dtype : ", array2.dtype)
# array2 내부 원소의 사이즈
print("array2의 itemsize : ", array2.itemsize)
# array2가 할당된 메모리의 크기
print("array2의 nbytes : ", array2.nbytes)
array2의 ndim : 2
array2의 shape : (3, 3)
array2의 size : 9
array2의 dtype : int32
array2의 itemsize : 4
array2의 nbytes : 36
Numpy Array의 Shape 변경
import numpy as np
arr = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
print(arr)
print(arr.shape)
print('--------------------')
# reshape
arr2 = arr.reshape(5, 2)
print(arr2)
print(arr2.shape)
[[ 1 2 3 4 5]
[ 6 7 8 9 10]]
(2, 5)
--------------------
[[ 1 2]
[ 3 4]
[ 5 6]
[ 7 8]
[ 9 10]]
(5, 2)
- reshape() 메서드를 이용하여 numpy array의 shape을 바꿀 수 있다.
Numpy 초기화 함수 이용하기
np.arange()
# np.arange() - 특정 범위를 지정하여 array 생성
# np.arange(start, stop, step)
print(np.arange(10))
print(np.arange(5, 10))
print(np.arange(0, 10, 2))
[0 1 2 3 4 5 6 7 8 9]
[5 6 7 8 9]
[0 2 4 6 8]
np.zeros()
# np.zeros() - 원소가 0인 array를 생성
print(np.zeros(10))
print(np.zeros((10, ), dtype=int))
print(np.zeros((2, 2)))
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0 0 0 0 0 0 0 0 0 0]
[[0. 0.]
[0. 0.]]
np.ones()
# np.ones() - 원소가 1인 array를 생성
print(np.ones(10))
print(np.ones((10, ), dtype=int))
print(np.ones((2, 2)))
[1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
[1 1 1 1 1 1 1 1 1 1]
[[1. 1.]
[1. 1.]]
np.full()
# np.full() - 모든 원소가 지정한 값을 갖는 array 생성
print(np.full((2, 2), np.inf))
[[inf inf]
[inf inf]]
np.eye()
# np.eye() - 단위행렬 생성
print(np.eye((5)))
[[1. 0. 0. 0. 0.]
[0. 1. 0. 0. 0.]
[0. 0. 1. 0. 0.]
[0. 0. 0. 1. 0.]
[0. 0. 0. 0. 1.]]
np.linspace()
# np.linspace() - 구간 array 생성
print(np.linspace(0, 1, 5)) # 0~1 사이를 5 구간으로 나눔
[0. 0.25 0.5 0.75 1. ]
np.empty()
# np.empty() - uninitialized array 생성
print(np.empty([2, 2], dtype=int))
[[ 1 256]
[ 65536 16777216]]
np.random
np.random.random()
np.random.random((2, 2))
array([[0.63445349, 0.41408872],
[0.78748439, 0.30736775]])
- 0~1까지의 랜덤한 숫자(float)를 2x2 크기로 생성
np.random.randint()
np.random.randint(0, 10, (2, 2))
array([[0, 1],
[9, 8]])
- 0~10까지의 랜덤한 숫자(int)를 2x2 크기로 생성
np.random.normal()
np.random.normal(0, 1, (2, 2))
array([[ 0.03333062, -0.12911341],
[ 2.34564391, -0.32281359]])
- 평균 0, 표준편차 1의 정규분포를 따르는 랜덤한 숫자를 2x2 크기로 생성
Numpy 슬라이싱/인덱싱
import numpy as np
temp = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
arr = np.array(temp) # 넘파이 배열 생성
arr
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
인덱싱
print(arr[2])
print(arr[2][1])
[7 8 9]
8
슬라이싱
a = arr[0:2, 0:2] # array의 0, 1번째 행의 0, 1번째 원소만 추출
b = arr[1:2, 1:] # array의 1번째 행의 1, 2번째 원소만 추출
print(a, '\n')
print(b)
[[1 2]
[4 5]]
[[5 6]]
Numpy Array Operation
- Numpy Array는 Vector처럼 사용할 수 있어 연산이 용이하다.
- 배열간 연산 가능
- +, -, *, / 등의 연산자 사용 가능
# 배열 생성
import numpy as np
v1 = np.array((1, 2, 3))
v2 = np.array((4, 5, 6))
덧셈
# vector addition
# (1, 2, 3) + (4, 5, 6)
print(v1 + v2)
[5 7 9]
뺄셈
# vector substraction
# (1, 2, 3) - (4, 5, 6)
print(v1 - v2)
[-3 -3 -3]
곱셈
- * 연산자에 의한 곱셈은 elemetwise multiplication으로, 각 원소마다 곱셈이 이루어진다.
# elementwise multiplication
# (1, 2, 3) * (4, 5, 6)
print(v1 * v2)
[4 10 18]
- multiply 함수를 이용하여도 동일하다.
# elementwise multiplication
# (1, 2, 3) * (4, 5, 6)
print(np.multiply(v1, v2))
[4 10 18]
나눗셈
- / 연산자에 의한 나눗셈은 elementwise division으로, 각 원소마다 나눗셈이 이루어진다.
# elementwise division
# (1, 2, 3) * (4, 5, 6)
print(v1 / v2)
[0.25 0.4 0.5]
- divide 함수를 이용하면 동일한 결과를 얻을 수 있다.
# elementwise division
# (1, 2, 3) * (4, 5, 6)
print(np.divide(v1, v2))
[0.25 0.4 0.5]
행렬 곱
- dot() 함수는 행렬 곱 연산을 진행한다.
import numpy as np
arr1 = [[1,2],[3,4]]
arr2 = [[5,6],[7,8]]
a = np.array(arr1)
b = np.array(arr2)
c= np.dot(a, b)
print(c)
[[19 22]
[43 50]]
원소의 합, 원소의 곱
원소의 합
- sum() 함수는 array 원소의 합을 구한다.
- axis를 지정하여 행, 열 별로 합을 구할 수 있다. (0 = 행 기준, 1 = 열 기준)
import numpy as np
a = np.array([[-1, 2, 3], [3, 4, 8]])
sum1 = np.sum(a)
sum2 = np.sum(a, axis=0)
sum3 = np.sum(a, axis=1)
print(sum1)
print(sum2)
print(sum3)
19
[2 6 11]
[4 15]
원소의 곱
- prod() 함수는 array 원소의 곱을 구한다.
import numpy as np
a = np.array([[1, 2, 3], [3, 4, 8]])
prod1 = np.prod(a)
prod2 = np.prod(a, axis=0)
prod3 = np.prod(b, axis=1)
print(prod1)
print(prod2)
print(prod3)
576
[3 8 24]
[6 96]
기타 연산
평균
- mean() 함수는 원소의 평균을 구한다.
import numpy as np
a = np.array([[-1, 2, 3], [3, 4, 8]])
mean1 = np.mean(a)
mean2 = np.mean(a, axis=0)
mean3 = np.mean(a, axis=1)
print(mean1)
print(mean2)
print(mean3)
3.1666666666666665
[1. 3. 5.5]
[1.33333333 5.]
표준편차
- std() 함수는 원소의 표준편차를 구한다.
import numpy as np
a = np.array([[-1, 2, 3], [3, 4, 8]])
std1 = np.std(a)
std2 = np.std(a, axis=0)
std3 = np.std(a, axis=1)
print(std1)
print(std2)
print(std3)
2.6718699236469
[2. 1. 2.5]
[1.69967317 2.1602469]
이외 각종 mathematical & statistics functions은 다음 사이트를 참고한다.
Broadcast 연산
- numpy는 서로 다른 array의 연산을 자동으로 broadcast한다.
import numpy as np
arr1 = np.array([[1, 2, 3], [4, 5, 6]])
arr2 = np.array([7, 8, 9])
Broadcast Sum
print(arr1 + arr2)
[[ 8 10 12]
[11 13 15]]
- arr2가 arr1의 각 행으로 broadcast되어 sum이 진행되었다.
Broadcast Multiplication
print(arr1 * arr2)
[[ 7 16 27]
[28 40 54]]
- arr2가 arr1의 각 행으로 broadcast되어 곱셈이 진행되었다.
Universal Functions
- numpy array는 하나의 연산으로 모든 원소에 동일한 연산을 진행할 수 있다.
import numpy as np
arr1 = np.array([[1, 2, 3], [4, 5, 6]])
print(1 / arr1)
print(arr1 + 3)
print(arr1 * 3)
[[1. 0.5 0.33333333]
[0.25 0.2 0.16666667]]
[[4 5 6]
[7 8 9]]
[[ 3 6 9]
[12 15 18]]
Masking
- True, False로 이루어진 array인 mask를 이용하여 원소 Filtering을 진행할 수 있다.
Mask 생성
import numpy as np
temp = np.array([1, 2, 3, 4, 5])
mask = temp > 2
print(mask)
array([False, False, True, True, True])
Filtering
data = np.random.randn(5, 5)
data
array([[-0.30519518, 0.53620961, 0.67420706, -0.03222147, 1.12299029],
[ 0.03689635, -0.00732184, -2.55542493, -0.77779374, -1.16346865],
[ 0.05040991, 0.87481013, -0.93257939, -0.0858221 , 1.48780203],
[-1.06143272, -1.26016532, 1.36892939, -2.10277946, 0.48490154],
[ 1.49290301, -0.25918333, 0.40908589, -0.03238321, -0.0917838 ]])
열 기준 filtering
data[:,mask]
array([[ 0.67420706, -0.03222147, 1.12299029],
[-2.55542493, -0.77779374, -1.16346865],
[-0.93257939, -0.0858221 , 1.48780203],
[ 1.36892939, -2.10277946, 0.48490154],
[ 0.40908589, -0.03238321, -0.0917838 ]])
행 기준 filtering
data[mask, :]
array([[ 0.05040991, 0.87481013, -0.93257939, -0.0858221 , 1.48780203],
[-1.06143272, -1.26016532, 1.36892939, -2.10277946, 0.48490154],
[ 1.49290301, -0.25918333, 0.40908589, -0.03238321, -0.0917838 ]])
Concatenation
- 서로 다른 array를 합치는 방법
기본 concatenate
1차원 배열
import numpy as np
arr1 = np.array([[1, 2, 3, 4]])
arr2 = np.array([[5, 6, 7, 8]])
np.concatenate([arr1, arr2]) # np.concatenate([데이터1, 데이터2, ...])
array([[1, 2, 3, 4],
[5, 6, 7, 8]])
- concatenate는 axis=0가 default로 설정되어 있다.
axis=1인 경우
import numpy as np
arr1 = np.array([[1, 2, 3, 4]])
arr2 = np.array([[5, 6, 7, 8]])
np.concatenate([arr1, arr2], axis=1) # np.concatenate([데이터1, 데이터2, ...])
array([[1, 2, 3, 4, 5, 6, 7, 8]])
- 옆방향으로 이어붙이기가 된다.
2차원 배열
import numpy as np
arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6], [7, 8]])
np.concatenate([arr1, arr2]) # np.concatenate([데이터1, 데이터2, ...])
array([[1, 2],
[3, 4],
[5, 6],
[7, 8]])
vertically concatenate
concatenate() - axis=0
np.concatenate([arr1, arr2], axis=0)
array([[1, 2, 3, 4],
[5, 6, 7, 8]])
vstack()
np.vstack([arr1, arr2])
array([[1, 2, 3, 4],
[5, 6, 7, 8]])
- vstack은 axis=0로 연결하는 것과 동일한 기능을 수행한다.
horizontally concatenate
concatenate() - axis=1
np.concatenate([arr1, arr2], axis=1)
array([[1, 2, 3, 4, 5, 6, 7, 8]])
hstack()
np.hstack([arr1, arr2])
array([[1, 2, 3, 4, 5, 6, 7, 8]])
- hstack은 axis=1로 연결하는 것과 동일한 기능을 수행한다.
Split
- 한 개의 Array를 여러 개의 Array로 분할하는 방법
np.split(어레이, [행 혹은 열 인덱스], axis=0)
# 행 혹은 열 인덱스는 분리하고자 하는 해당 인덱스의 번호를 적는다.
행 단위로 자르기 (axis=0)
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
np.split(arr, [1], axis=0)
[array([[1, 2, 3]]),
array([[4, 5, 6],
[7, 8, 9]])]
- 1번 행 인덱스을 기준으로 numpy array가 2개로 분할되었다.
열 단위로 자르기 (axis=1)
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
np.split(arr, [1], axis=1)
[array([[1],
[4],
[7]]),
array([[2, 3],
[5, 6],
[8, 9]])]
- 1번 열 인덱스를 기준으로 numpy array가 2개로 분할되었다.