numpy
numerical python의 약자이며 python의 고성능 과학 계산용 라이브러리이다.
선형대수 및 여러 통계와 관련된 함수를 제공한다.
numpy
에서 배열(array)를 ndarray
라 부른다.
ndarray
의 값들은 list
와 달리 모두 동일한 데이터 타입을 가진다.
또한 정형화된 배열이다.
import numpy as np
# shape은 ndarray의 각 axis의 차원 수를 나타낸다.
# axis는 ndarray의 축을 나타내며 축에 따라 몇차원인지를 나타낸다.
# 여기서는 axis=0 일때 2차원, axis=1 일때 3차원을 나타낸다.
arr = np.array([1, 2, 3], [4, 5, 6])
print(arr.shape) # (2, 3)
arr = np.array([1, 2, 3], dtype=np.int32)
# int타입의 ndarray에 float타입의 데이터를 입력하면 소수점 이하를 무시한다.
arr[0] = 99.99
print(arr) # array([99, 2, 3])
# 데이터 타입을 바꾸려면 astype을 사용한다.
arr = arr.astype(np.float32)
arr[0] = 87.9 # 가능
print(arr) # array([87.9, 2, 3])
# l은 list안에 list로 되어있는데 내부 list의 길이가 다 다르다.
l = [[1, 2], [3, 4, 5, 6, 7], [8, 9, 10]]
# arr는 3행 2열의 행렬이다.
# 각 행의 원소의 갯수는 모두 같아야 한다.
# 정형화된 구조를 갖고 있다.
arr = np.array([[1, 2], [3, 4], [5, 6]])
ndarray
의 데이터 타입에 따라 데이터 크기가 달라진다.
float32
는 float을 32bit로 나타낸다는 뜻이고 ndarray
의 값 하나당 4byte(32bit)를 차지한다.
int8
은 int를 8bit로 나타내며 ndarray
의 값 하나당 1byte(8bit)를 차지한다.
broadcasting
not yet
indexing
ndarray
는 axis(축)
을 가지고 있으며 각 축에 대해서 indexing을 할 수 있다.
다음은 list
의 indexing과 ndarray
의 indexing을 비교이다.
l = [[1, 2, 3], [4, 5, 6]]
print(l[0][1]) # 2
print(l[1][-1]) # 6
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6]])
print(arr[0, 1]) # 2
print(arr[1, -1]) # 6
boolean indexing
은 boolean ndarray
혹은 boolean list
로 indexing하는 방법이다.
import numpy as np
arr = np.arange(12).reshape(-1, 4)
# arr의 값 중 4의 배수를 찾아보자.
# arr와 idx array의 shape이 같으면 1D array를 반환한다.
idx1 = arr % 4 == 0
print(idx1) # [[True, False, False, False], [True, False, False, False], [True, False, False, False]]
print(arr[idx1]) # [0, 4, 8]
# axis=0의 0, 1번째 벡터가 선택되었다.
idx2 = np.array([True, True, False])
print(arr[idx2]) # [[0, 1, 2, 3], [4, 5, 6, 7]]
# axis=1의 0, 3번째 벡터를 원한다.
# 하지만 boolean indexing은 row-major이다.
# 즉, indexing array의 shape과 array의 shape이 일치하지 않으면 axis=0의 차원과 비교한다.
idx3 = np.array([True, False, False, True])
print(arr[idx3]) # IndexError
print(arr[:, idx3]) # [[0, 3], [4, 7], [8, 11]]
# boolean indexing에 꼭 ndarray가 아니어도 된다.
arr2 = np.arange(12).reshape(-1, 2, 3) # shape: (2, 2, 3)
idx4 = [True, False, True]
print(arr2[:, :, idx4])
slicing
list
의 slicing은 한 row에 대해서만 indexing이 가능했다.
l1 = [1, 2, 3, 4, 5]
print(l1[2:4]) # [3, 4]
l2 = [[1, 2, 3], [4, 5, 6, 7, 8], [9, 10, 11]]
print(l2[1][0:2]) # [4, 5]
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(arr[0, 0]) # 1
print(arr[0, 2]) # 3
print(arr[1, 0:2]) # [4, 5]
print(arr[0:2, 2]) # [3, 6]
print(arr[0:2, 1:3]) # [[2, 3], [5, 6]]
ndarray
의 값에 접근하는 게 더 편리해졌다!
numpy method
np.empty
는 shape
을 인자로 받아서 그에 해당하는 ndarray
를 반환한다.
이때 내부 값들은 초기화되지 않은 상태이다.
즉, 할당받은 ndarray
의 일부 혹은 전체가 이전에 사용하던 ndarray
일 수도 있다.
np.vstack
과 np.hstack
은 ndarray
를 axis
0과 1로 합치는 메소드이다.
import numpy as np
arr1 = np.arange(12).reshape(-1, 2, 3)
arr2 = np.arange(12, 24).reshape(-1, 2, 3)
arr3 = np.vstack((arr1, arr2))
print(arr3.shape) # (4, 2, 3)
arr4 = np.hstack((arr1, arr2))
print(arr4.shape) # (2, 4, 3)
np.vstack
과 np.hstack
은 합치려는 축이 고정되어 있다.
축을 정해 두 ndarray
를 합치는 함수는 np.concatenate
이다.
import numpy as np
arr1 = np.arange(12).reshape(-1, 2, 3)
arr2 = np.arange(12, 24).reshape(-1, 2, 3)
arr3 = np.concatenate((arr1, arr2), axis=0)
print(arr3.shape) # (4, 2, 3)
arr4 = np.concatenate((arr1, arr2), axis=1)
print(arr4.shape) # (2, 4, 3)
arr5 = np.concatenate((arr1, arr2), axis=2)
print(arr5.shape) # (2, 2, 6)
np.where
는 조건의 참, 거짓에 따라 값을 반환해준다.
# arr1의 값 중 1보다 크다면 99, 그렇지 않다면 -100을 반환한다.
import numpy as np
arr1 = np.array([[4, 2, 1], [6, -1, 3]])
arr2 = np.where(arr1 > 1, 99, -100)
print(arr2) # [[99, 99, -100], [99, -100, 99]]