Week02 Day06

 

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

ndarrayaxis(축)을 가지고 있으며 각 축에 대해서 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 indexingboolean 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.emptyshape을 인자로 받아서 그에 해당하는 ndarray를 반환한다.
이때 내부 값들은 초기화되지 않은 상태이다.
즉, 할당받은 ndarray의 일부 혹은 전체가 이전에 사용하던 ndarray일 수도 있다.

np.vstacknp.hstackndarrayaxis0과 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.vstacknp.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]]