본문 바로가기

프로그래밍/for AI

[Data] numpy 핵심 기능 정리

다차원의 행렬의 연산에 최고의 선택
pandas의 기반 데이터 구조

 

Numpy(Numerical Python)

https://numpy.org/

 

NumPy

Use the interactive shell to try NumPy in the browser

numpy.org

정의 

 

과학 및 수학 데이터 분석에서 다차원 행렬을 다루고 연산하기 위한 파이썬 라이브러리

 

목적

 

파이썬에서 리스트 튜플의 데이터를 넘파이 배열로 바꾸어 좀 더 효율적이고 쉽게 행렬연산을 할수있도록 함

 

특징

 

1.  데이터 타입

> ndarray(리스트와 유사)
# 여러개의 축(axis, 차원)을 다룰 수 있음

 

2. View and Copy

> View : 얕은 복사, 임시저장, 상호 연결
# in numpy: the internal data buffer directly using a view (buffer란 임시저장공간, queue라고도 함)
# splicing(array[a:b])은 ndarray의 View를 생성 -> python list에서는 splicing된 리스트는 copy를 형성
# python의 얕은 복사의 개념 :원본과 연결되어 서로의 값의 변경이 반영됨
> Copy : 깊은 복사, 독립적 객체 생성
# 깊은 복사를 위해서는 array.copy() 
# dtype = object 일때 array.deepcopy()


3. 유니버셜 함수

> 유니버셜함수(ufunc)
# numpy에서 한개 또는 두개 이상의 배열을 받아 벡터화 연산을 지원하는 함수
# 벡터화 연산과 브로드캐스팅을 지원
> 벡터화 연산(vectorization)
# 배열에 연산을 각 인자에 동시에 수행한다. (list for반복보다 효율적)
> 브로드캐스팅
# 크기가 다른 배열간 연산을 위해 크기가 1인 배열의 인자를 확장한 것처럼 작동하여 다른 배열에 백터화 연산 수행
# [1,2,3]이 있을 때, 모양이 (3,)인 1차원 배열 -> 브로드캐스팅 -> (1,3)인 2차원 배열
# ex) [1,2,3] (1차원) -> [[1,2,3]] (2차원) 
# 실제로 2차원이 된 것이 아닌 numpy 연산에서 1차원 배열을 2차원 처럼 자동으로 맞추어 연산(메모리 사용없음)

 

기능

 

0. 라이브러리 호출 

> import numpy as np
# 라이브러리 호출


1. ndarray 생성 및 확인 : array, shape, ndim

> array = np.array(list)
# 리스트를 받아 ndarray로 변환 
> print(type(array))
# ndarray로 잘 생성되었는지 확인
> array.shape
# (row 개수, column 개수)를 튜플로 반환
> array.ndim
# 차원(축의 개수)를 반환


2. 기본값이 있는 ndarray 생성 : arange, zeros, ones

> sequence_array = np.arange(10)
# 0~9까지 정수가 담긴 배열
> zero_array = np.zeros((3,2), dtype='int32')
# shape = (3,2)이고 0으로 채워진 배열 / dtype(dafault) = 'float64'
> one_array = np.ones((3,2))
# shape = (3,2)이고 1 로 채워진 배열


3. ndarray의 모양 및 크기 변경 : reshape, resize

> array2  = array1.reshape(2,5) 
# array1.shape이 (10, ) 일때, (2, 5)로 shape을 변경
> array2 = array1.reshape(-1, 5)
# -1을 인자로 사용 : 열의 개수를 5가 되도록 행의 개수를 조정하여 shape 변경
> arr = np.array([1,2,3,4])
> arr_re = np.resize(arr, (2,3))
[[1 2 3]
 [4 1 2]]
# 원하는 모양으로 바꾸고, 부족한 부분은 원 배열인 arr의 값을 인덱스 빠른 것부터 새로운 배열의 끝에 채움

# 원본 배열 영향없음, 새로운 배열 도출
> arr.resize(2,3)
[[1 2 3]
 [4 0 0]]
# 원하는 모양으로 바꾸고, 부족한 부분은 새로운 배열의 끝에 0을 채움

# 대상 배열의 값을 직접 변경 / 반환값 없음! 


4. ndarray의 Indexing&Slicinig : 인덱싱, 스플라이싱, 팬시 인덱싱, 불린 인덱싱

> array[1,2] 
# 배열 내 index가 row = 1, col =2 에서의 값을 가져옴(인덱싱)
> array3=. array[1:3] 
# array 배열 내 index가 1~2까지인 값 불러와서 저장(스플라이싱)
> array_2d = np.arange(1, 10).reshape(3,3)
> array_2d_index = array_2d[0:2, 1:3]
# 2차원 ndarray에서 axis1 = 0~1, axis2 = 1~2인 값을 읽어옴
# 주의! ndarray의 splicing은 얕은 복사(View) -> 원본에 영향
> array4 = array_2d[[0,2],2] 
# 팬시 인덱싱 : row = 0, 2 / col = 2인 ndrray를 반환
> array5 = array_2d[array_2d >= 5]
# 불린 인덱싱1: 값이 5이상인 값만을 담은 1차원 ndarray 반환
> array5 = array_2d >= 5
# 불린 인덱싱2 : 값이 5이상이면 True를, 이하면 False을 인자로 하는 ndarray반환(shape 유지)


5. ndarray의 정렬 : sort, argsort

> array = arange([1,4,2,9])
> array_sorted= np.sort(array)
# 배열을 정렬한 ndarray를 반환
# 내림차순은 [::-1]을 붙혀서 구현
> array_sorted2 = array.sort() 
# > array.sort() 만 해도 됨
# 원본 array를 정렬한 형태로 변환 / 반환값은 없음(array_sorted2=None)
> array_sorted_idx = np.argsort(array)
# 원래 배열에서의 인덱스(위치) 정보를 (오른차순으로) 정렬된 순서 위치에 넣어서 반환
# 내림차순은 [::-1]을 붙혀서 구현

 

6. 행렬의 내적과 전치: dot, transpose

> dot_product  = np.dot(A,B)
# A(2x3)와 B(3X2) 행렬의 내적을 반환
> trnspose_mat = np.transpose(A)
# A행렬의 행과 열을 바꾼 행렬을 반환(2x3 -> 3x2)

 

7. 차원(axis)을 추가 : newaxis

> array = np.array([0, 1, 2])
# 1차원의 ndarray 배열
> new_arr = array[ : , np.newaxis]
[[0]
 [1]
 [2]]

# 2차원의 ndarray 배열
# 기존의 array를 x축으로 하고 y축 추가(1차원에서는 한개의 축만 존재했었음)
# np.newaxis 대신에 None을 넣어도 된다. 

 

8. 브로드캐스팅 연산 : 내적 , 외적

> x = np.arange(3) # [0,1,2]
> y = np.arange(3, 6) # [3,4,5]
# 두 배열 정의
> x[:]*y
array([ 0,  4, 10])
# inner product(내적)
# 동일한 위치의 요소끼리의 곱
> x[ : , np.newaxis]* y
array([[ 0,  0,  0],
       [ 3,  4,  5],
       [ 6,  8, 10]])

# outer product(외적)
# 브로드캐스팅 연산으로 y를 x의 크기에 맞춰 연산(한 배열의 차원의 크기가 1일때 적용가능)
# x의 모양(3,1), y의 모양(1,3) -> (3,3) 배열 생성 / x는 newaxis로 2차원이 됬고, y는 브로드캐스팅으로 x에 맞춤

 

9. 축(axis)을 기준으로 최대 최소 구하기 : min, max

> array = np.array([[3, 7, 2], [8, 4, 6]])
> print(np.max(array))
# 전체 원소를 대상으로 최댓값-> 8
> print(np.max(array, axis = 0))
# X축(위에서 아래방향, col)를 기준으로 각각 최댓값 -> [8 7 6]
> print(np.max(array, axis = 1))
# Y축(좌측에서 우측방향, row)을 기준으로 각각 최댓값 -> [7 8]