[파이썬 머신러닝 완벽 가이드] 1장-2.넘파이
2. 넘파이
- 넘파이의 기반 데이터 타입 : ndarray
- ndarray를 이용해 넘파이에서 다차원 배열을 쉽게 생성하고 다양한 연산을 수행할 수 있다.
1) ndarray 생성
import numpy as np
array1 = np.array([1,2,3])
print(type(array1))
print(array1.shape)
----------------------------
<class 'numpy.ndarray'>
(3,) : 1차원 array로 3개의 데이터를 가지고 있음을 뜻함
array2 = np.array([[1,2,3],[2,3,4]])
print(type(array2))
print(array2.shape)
----------------------------
<class 'numpy.ndarray'>
(2, 3) : 2차원 array로 2개의 로우와 3개의 칼럼으로 구성되어 있음을 뜻함
array3 = np.array([[1,2,3]])
print(type(array3))
print(array3.shape)
----------------------------
<class 'numpy.ndarray'>
(1, 3) : 2차원 array로 1개의 로우와 3개의 칼럼으로 구성되어 있음
2) ndim : ndarray의 차원 확인
print(array2.ndim)
----------------------------
2
3) ndarray의 데이터 타입
- ndarray 내의 데이터 값은 숫자 값, 문자열 값, 불 값 등 모두 가능
- 숫자형
- int형 (8bit, 16bit, 32bit)
- unsigned int형 (8bit, 16bit, 32bit)
- float 형(16bit, 32bit, 64bit, 128bit)
- 더 큰 숫자 값이나 정밀도 → complex 타입
- ndarray 내의 데이터 타입은 연산의 특성상 같은 데이터 타입만 가능함. 즉, 한 개의 ndarray 객체에 int와 float가 함께 있을 수 없다.
-
dtype : ndarray의 데이터 타입 확인
list1 = [1,2,3] print(type(list1)) array1 = np.array(list1) print(type(array1)) print(array1.dtype) ------------------------ <class 'list'> <class 'numpy.ndarray'> int32
-
만약 다른 데이터 유형이 섞여있는 리스트를 ndarray로 변경하면 데이터 크기가 더 큰 데이터 타입으로 형 변환을 일괄 적용한다.
list2 = [1, 2, 'test'] array2 = np.array(list2) print(array2.dtype) print(array2) --------------------------- <U11 ['1' '2' 'test']
list3 = [1, 2, 3.0] array3 = np.array(list3) print(array3.dtype) print(array3) --------------------------- float64 [1. 2. 3.]
4) ndarray 형변환
- ndarray 내 데이터 값의 타입을 변경할 수 있다.
array_int = np.array([1,2,3])
array_float = array_int.astype('float64')
print(array_float, array_float.dtype)
------------------------------------------
[1. 2. 3.] float64
array_float1 = np.array([1.1,2.1,3.1])
array_int1 = array_int.astype('int32')
print(array_int1, array_int1.dtype)
-------------------------------------------
[1 2 3] int32
5) ndarray를 편리하게 생성하기
-
arange(x) : 0부터 x까지의 값을 순차적으로 담는다.
sequence_array = np.arange(10) print(sequence_array) print(sequence_array.dtype, sequence_array.shape) ----------------------------------------------- [0 1 2 3 4 5 6 7 8 9] int32 (10,)
sequence_array = np.arange(2, 10) print(sequence_array) print(sequence_array.dtype, sequence_array.shape) ----------------------------------------------- [2 3 4 5 6 7 8 9] int32 (8,)
- zeros() : 함수 인자로 튜플 형태의 shape 값을 입력하면 해당 shape의 모든 값을 0으로 채운 ndarray를 반환한다.
-
ones() : zeros와 유사하나 모든 값을 1로 채운 값을 반환한다.
zero_array = np.zeros((3,2), dtype='int32') zero_array --------------------------------------------- array([[0, 0], [0, 0], [0, 0]])
one_array = np.ones((3,2), dtype='int32') one_array --------------------------------------------- array([[1, 1], [1, 1], [1, 1]])
6) reshape(): ndarray의 차원 및 크기 변경
array1 = np.arange(10)
array2 = array1.reshape(2, 5)
print(array2)
-----------------------------
[[0 1 2 3 4]
[5 6 7 8 9]]
array1 = np.arange(10)
print(array1)
## -1을 입력하면, 5열에 맞는 행의 수가 알아서 맞춰진다.
array2 = array1.reshape(-1,5)
print('array2 shape:',array2.shape)
array3 = array1.reshape(5,-1)
print('array3 shape:',array3.shape)
--------------------------------------
[0 1 2 3 4 5 6 7 8 9]
array2 shape: (2, 5)
array3 shape: (5, 2)
7) indexing
-
단일값 추출
array1 = np.arange(10) print(array1) # [0 1 2 3 4 5 6 7 8 9] print(array1[1]) # 1
array1 = np.arange(1, 10) array2d = array1.reshape(3,3) print(array2d) ---- [[1 2 3] [4 5 6] [7 8 9]] print(array2d[2,2]) # 9
- slicing
- 넘파이에서 ndarray 내의 일부 데이터 세트나 특정 데이터만을 선택할 수 있도록 한다.
array1 = np.arange(1, 10) array2d = array1.reshape(3,3) print(array2d[0:2,0:2]) -------------- [[1 2] [4 5]] print(array2d[1:3,:],'\n') -------------- [[4 5 6] [7 8 9]] print(array2d[1:3,:2],'\n') ------------------- [[4 5] [7 8]]
- fancy indexing
- 리스트나 ndarray로 인덱스 집합을 지정 → 해당 위치의 인덱스에 해당하는 ndarray를 반환하는 인덱싱 방식
array1 = np.arange(1,10) array2d = array1.reshape(3,3) array3 = array2d[[0,2], 0:2] print(array3) ------------------ [[1 2] [7 8]] array4 = array2d[[0,1]] print(array4) ------------------- [[1 2 3] [4 5 6]]
- boolean indexing
- 조건 필터링과 검색을 동시에 할 수 있기 때문에 자주 사용되는 인덱싱 방식
array1 = np.arange(1,10) array_filtered = array1[array1 > 5] print(array_filtered) # [6 7 8 9] print(array1 > 5) # [False False False False False True True True True] boolean_index = np.array([False False False False False True True True True]) array_filtered2 = array1[boolean_index ]; print(array_filtered2) # [6 7 8 9]
8) 행렬의 정렬 - sort()와 argsort()
-
행렬 정렬
org_array = np.array([ 3, 1, 9, 5]) print('원본 행렬:', org_array) # np.sort( )로 정렬 sort_array1 = np.sort(org_array) print (sort_array1) # np.sort 함수가 반환한 값 : [1 3 5 9] -> 정렬됨 print(org_array) # 원본 행렬 : [3 1 9 5] -> 그대로 # ndarray.sort()로 정렬 sort_array2 = org_array.sort() print(sort_array2) # None -> 아무것도 반환 안함 print(org_array) # 원본 행렬 : [1 3 5 9] -> 원본 행렬이 정렬됨
- 내림차순 정렬
sort_array1_desc = np.sort(org_array)[::-1] print ('내림차순으로 정렬:', sort_array1_desc) # [9 5 3 1]
- 2차원 행렬의 정렬
- axis=0 : 로우 방향으로 정렬
array2d = np.array([[8, 12], [7, 1 ]]) sort_array2d_axis0 = np.sort(array2d, axis=0) print('로우 방향으로 정렬:\n', sort_array2d_axis0) [[ 7 1] [ 8 12]]
- axis=1 : 컬럼 방향으로 정렬
sort_array2d_axis1 = np.sort(array2d, axis=1) print('컬럼 방향으로 정렬:\n', sort_array2d_axis1) [[ 8 12] [ 1 7]]
-
정렬된 행렬의 인덱스 반환
org_array = np.array([ 3, 1, 9, 5]) sort_indices = np.argsort(org_array) print(type(sort_indices)) # <class 'numpy.ndarray'> print('행렬 정렬 시 원본 행렬의 인덱스:', sort_indices) # [1 0 3 2]
org_array = np.array([ 3, 1, 9, 5]) sort_indices_desc = np.argsort(org_array)[::-1] # 9,5,3,1 print('행렬 내림차순 정렬 시 원본 행렬의 인덱스:', sort_indices_desc) # [2 3 0 1]
name_array = np.array(['John', 'Mike', 'Sarah', 'Kate', 'Samuel']) score_array= np.array([78, 95, 84, 98, 88])
9) 선형 대수 연산 - 행렬 내적과 전치 행렬 구하기
- 행렬 내적
- 행렬 곱을 의미
- 두 행렬 A, B의 내적은 np.dot()을 이용해 계산한다.
- 아래 그림에서 np.dot()의 1행 1열 값은 A 행렬의 1행과 B 행렬의 1열 값을 순차적으로 곱하여 더한 값이다. 58 = 17 + 29 + 3*11
A = np.array([[1, 2, 3],
[4, 5, 6]])
B = np.array([[7, 8],
[9, 10],
[11, 12]])
dot_product = np.dot(A, B)
print('행렬 내적 결과:\n', dot_product)
------------------------------------------
[[ 58 64]
[139 154]]
- 전치 행렬
- 원 행렬에서 행과 열 위치를 교환한 원소로 구성한 행렬을 그 행렬의 전치 행렬이라 한다.
- 2x2 행렬 A가 있을 경우 A 행렬의 1행 2열의 원소를 2행 1열의 원소로, 2행 1열의 원소를 1행 2열의 원소로 교환한다.
A = np.array([[1, 2], [3, 4]]) transpose_mat = np.transpose(A) print('A의 전치 행렬:\n', transpose_mat) ------------------------------------------------------------------ [[1 3] [2 4]]