8 분 소요

-> 파이썬의 대표적인 배열(array) 라이브러리
-> 벡터 및 행렬 연산에 있어 매우 편리한 기능을 제공

1. Numpy 정의

import numpy as np

2. Array 정의 및 형태 확인

  • type 확인 : type(~)
  • 배열 구조 확인 : ~.shape
  • 배열 차원 확인하기 : ~.ndim
# array정의 
array1 = np.array([1,2,3])
print(f"array1 type : {type(array1)}")      # type 확인
print(f"array1 array 형태 : {array1.shape}\n") # 배열 형태 확인

array2 = np.array([[1,2,3],
                 [2,3,4]])
print(f"array2 type : {type(array2)}")
print(f"array2 array 형태 : {array2.shape}\n")

array3 = np.array([[1,2,3]])
print(f"array3 type : {type(array3)}")
print(f"array3 array 형태 : {array3.shape}\n")

# 차원 확인
print(f"array1 : {array1.ndim}차원, array2 : {array2.ndim}차원, array3 : {array3.ndim}차원")
array1 type : <class 'numpy.ndarray'>
array1 array 형태 : (3,)

array2 type : <class 'numpy.ndarray'>
array2 array 형태 : (2, 3)

array3 type : <class 'numpy.ndarray'>
array3 array 형태 : (1, 3)

array1 : 1차원, array2 : 2차원, array3 : 2차원

3. ndarray의 데이터 타입

  • ndarray는 데이터값이 모두 같은 데이터 타입이어야 한다.
  • 데이터 타입 확인 하기 : ~.dtype
# list -> ndarray로 변환
list1 = [1,2,3]
print(type(list1))

array1 = np.array(list1)
print(type(array1))

print(array1, array1.dtype) 
<class 'list'>
<class 'numpy.ndarray'>
[1 2 3] int64
# 하나의 문자열로 인하여 모두 문자열로 변환
list2 = [1,2,'test']
array2 = np.array(list2)
print(array2, array2.dtype)

# 하나의 실수로 인하여 전부 실수형으로 변환
list3 = [1,2, 3.0]
array3 = np.array(list3)
print(array3, array3.dtype)
['1' '2' 'test'] <U21
[1. 2. 3.] float64
# int64 -> float64로 형 변환
array_int = np.array([1,2,3])
array_float = array_int.astype('float64')
print(array_float, array_float.dtype)

# float64 -> int32로 형 변환
array_int1 = array_float.astype('int32')
print(array_int1, array_int1.dtype)

# float63 -> int32로 형 변환 | 소수점 아래 사라짐
array_float1 = np.array([1.1, 2.1, 3.1])
array_int2 = array_float1.astype('int32')
print(array_int2, array_int2.dtype)
[1. 2. 3.] float64
[1 2 3] int32
[1 2 3] int32

4. ndarray 생성하기 - arange, zeros, ones

# arange() : 0부터 함수 인자 값 -1 까지 값을 순차적으로 ndarray의 데이터값으로 변환
sequence_array = np.arange(10)
print(sequence_array)
print(f"dtype: {sequence_array.dtype} | shape: {sequence_array.shape}\n")

# zeros() : 모든 값을 0으로 채운 해당 shape를 가진 ndarray를 반환
zero_array = np.zeros((3,2), dtype = 'int32')
print(zero_array)
print(f"dtype: {zero_array.dtype} | shape : {zero_array.shape}\n")

# ones() : 모든 값을 1으로 채운 ndarray를 반환
one_array = np.ones((3,2))
print(one_array)
print(f"dtype: {one_array.dtype} | shape : {one_array.shape}")
[0 1 2 3 4 5 6 7 8 9]
dtype: int64 | shape: (10,)

[[0 0]
 [0 0]
 [0 0]]
dtype: int32 | shape : (3, 2)

[[1. 1.]
 [1. 1.]
 [1. 1.]]
dtype: float64 | shape : (3, 2)

5. ndarray의 차원과 크기를 변경하는 reshape()

# 배열 정의 
array1 = np.arange(10)
print(f"array1:\n {array1}")

# 1*10 -> 2*5
array2 = array1.reshape(2,5)
print(f"array2:\n {array2}")

# 1*10 -> 5*2
array3 = array1.reshape(5,2)
print(f"array3:\n {array3}")
array1:
 [0 1 2 3 4 5 6 7 8 9]
array2:
 [[0 1 2 3 4]
 [5 6 7 8 9]]
array3:
 [[0 1]
 [2 3]
 [4 5]
 [6 7]
 [8 9]]
# error 지정된 사이즈로 변경이 불가능 하면 오류 발생
array1.reshape(4,3)
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

Cell In[8], line 2
      1 # error 지정된 사이즈로 변경이 불가능 하면 오류 발생
----> 2 array1.reshape(4,3)


ValueError: cannot reshape array of size 10 into shape (4,3)
# -1을 인자로 사용하면 원래 ndarray와 호환되는 새로운 shape로 변환
array1 = np.arange(10)
print(array1)
array2 = array1.reshape(-1,5)
print(f"array2 shape: {array2.shape}")
array3 = array1.reshape(5,-1)
print(f"array3 shape: {array3.shape}")
[0 1 2 3 4 5 6 7 8 9]
array2 shape: (2, 5)
array3 shape: (5, 2)
# 호환될 수 없는 형태라 error
array1 = np.arange(10)
array3 = array1.reshape(-1,4)
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

Cell In[10], line 3
      1 # 호환될 수 없는 형태라 error
      2 array1 = np.arange(10)
----> 3 array3 = array1.reshape(-1,4)


ValueError: cannot reshape array of size 10 into shape (4)
array1 = np.arange(8)
array3d =array1.reshape((2,2,2))
print(f"array3:\n {array3d.tolist()}\n")

# 3차원 ndarray를 2차원 ndarray로 변환
array5 = array3d.reshape(-1, 1)
print(f"array5:\n {array5.tolist()}")
print(f"array5 shape: {array5.shape}\n")

# 1차원 ndarray를 2차원 ndarray로 변환
array6 = array1.reshape(-1, 1)
print(f"array6:\n {array6.tolist()}")
print(f"array6 shape: {array6.shape}\n")
array3:
 [[[0, 1], [2, 3]], [[4, 5], [6, 7]]]

array5:
 [[0], [1], [2], [3], [4], [5], [6], [7]]
array5 shape: (8, 1)

array6:
 [[0], [1], [2], [3], [4], [5], [6], [7]]
array6 shape: (8, 1)

6. 넘파이의 ndarray의 데이터 세트 선택하기 - 인덱싱(Indexing)

  1. 특정한 데이터만 추출 : 원하는 위치의 인덱스 값을 지정하면 해당 위치의 데이터가 반환됩니다.
  2. 슬라이싱(Slicing) : 슬라이싱은 연속된 인덱스상의 ndarray를 추출하는 방식
  3. 팬시 인덱싱(Fancy Indexing) : 일정한 인덱싱 집합을 리스트 또는 ndarray형태로 지정해 해당 위치에 있는 데이터의 ndarray를 반환
  4. 불린 인덱싱(Boolean Indexing) : 특정 조건에 해당하는지 여부인 True/False 값 인덱싱 집한을 기반으로 True에 해당하는 인덱스 위치에 있는 데이터의 ndarray를 반환

1. 단일 값 추출

# 1부터 9까지의 1차원 ndarray 생성
array1 = np.arange(start = 1, stop = 10)
print(f'array1: {array1}')

# index는 0부터 시작하므로 array1[2]는 3번째 index 위치의 데이터값을 의미
value = array1[2]
print(f"value: {value}")
print(type(value))
array1: [1 2 3 4 5 6 7 8 9]
value: 3
<class 'numpy.int64'>
print(f"맨 뒤의 값: {array1[-1]} 맨뒤에서 두 번째 값: {array1[-2]}")
맨 뒤의 값: 9 맨뒤에서 두 번째 값: 8
# ndarray내의 데이터 값 수정
print(f"array1 : {array1}")
array1[0] = 9
array1[8] = 0
print(f"변경된 array1 : {array1}")
array1 : [1 2 3 4 5 6 7 8 9]
변경된 array1 : [9 2 3 4 5 6 7 8 0]
array1d = np.arange(start = 1, stop = 10)
array2d = array1d.reshape(3,3)
print(array2d)

print(f"(row = 0, col = 0) index 가리키는 값: {array2d[0,0]}")
print(f"(row = 0, col = 1) index 가리키는 값: {array2d[0,1]}")
print(f"(row = 1, col = 0) index 가리키는 값: {array2d[1,0]}")
print(f"(row = 2, col = 2) index 가리키는 값: {array2d[2,2]}")
[[1 2 3]
 [4 5 6]
 [7 8 9]]
(row = 0, col = 0) index 가리키는 값: 1
(row = 0, col = 1) index 가리키는 값: 2
(row = 1, col = 0) index 가리키는 값: 4
(row = 2, col = 2) index 가리키는 값: 9

2. 슬라이싱

  • ’;’ 기호 앞에 시작 인덱스를 생략하면 자동으로 맨 처음 인덱스인 0으로 간주
  • ’:’ 기호 뒤에 종료 인덱스를 생략하면 자동으롬 맨 마지막 인덱스로 간주
  • ’:’ 기호 앞/뒤에 시작/종료 인덱스를 생략하면 자동으로 맨 처음/맨 마지막 인덱스로 간주
array1 = np.arange(start = 1, stop = 10)
array3 = array1[0:3]
print(array3)
print(type(array3))
[1 2 3]
<class 'numpy.ndarray'>
array1 = np.arange(start = 1, stop = 10)
array4 = array1[:3]
print(array4)

array5 = array1[3:]
print(array5)

array6 = array1[:]
print(array6)
[1 2 3]
[4 5 6 7 8 9]
[1 2 3 4 5 6 7 8 9]
array1d = np.arange(start = 1, stop = 10)
array2d = array1d.reshape(3,3)
print(f"array2d:\n {array2d}")

print(f"array2d[0:2, 0:2]:\n {array2d[0:2, 0:2]}")
print(f"array2d[1:3, 0:3]:\n {array2d[1:3, 0:3]}")
print(f"array2d[1:3, :]:\n {array2d[1:3, :]}")
print(f"array2d[: , :]:\n {array2d[:, :]}")
print(f"array2d[:2, 1:]:\n {array2d[:2, 1:]}")
print(f"array2d[:2, 0]:\n {array2d[:2, 0]}")
array2d:
 [[1 2 3]
 [4 5 6]
 [7 8 9]]
array2d[0:2, 0:2]:
 [[1 2]
 [4 5]]
array2d[1:3, 0:3]:
 [[4 5 6]
 [7 8 9]]
array2d[1:3, :]:
 [[4 5 6]
 [7 8 9]]
array2d[: , :]:
 [[1 2 3]
 [4 5 6]
 [7 8 9]]
array2d[:2, 1:]:
 [[2 3]
 [5 6]]
array2d[:2, 0]:
 [1 4]
print(array2d[0])
print(array2d[1])
print(f"array2d[0] shape : {array2d[0].shape} | array2d[1] shape: {array2d[1].shape}")
[1 2 3]
[4 5 6]
array2d[0] shape : (3,) | array2d[1] shape: (3,)

3. 팬시 인덱싱(Fancy Indexing)

array1 = np.arange(start = 1, stop = 10)
array2d = array1d.reshape(3,3)

array3 = array2d[[0,1] ,2]
print(f"array2d[[0, 1],2] => {array3.tolist()}")

array4 = array2d[[0,1] ,0:2]
print(f"array2d[[0, 1], 0:2] => {array4.tolist()}")

array5 = array2d[[0,1]]
print(f"array2d[[0, 1],2] => {array5.tolist()}")
array2d[[0, 1],2] => [3, 6]
array2d[[0, 1], 0:2] => [[1, 2], [4, 5]]
array2d[[0, 1],2] => [[1, 2, 3], [4, 5, 6]]

4. 불린 인덱싱(Boolean Indexing)

  • 조건 필터링과 검색을 동시에 할 수 있음
array1d = np.arange(start = 1, stop = 10)
# [ ]안에 array1d > 5 Boolean Indexing을 적용
array3 = array1d[array1d > 5]
print(f"array1d > 5 불린 인덱싱 결과 값: {array3}")
array1d > 5 불린 인덱싱 결과 값: [6 7 8 9]
array1d > 5
array([False, False, False, False, False,  True,  True,  True,  True])
boolean_indexes = np.array([False, False, False, False, False,  True,  True,  True,  True])
array3 = array1d[boolean_indexes]
print(f"불린 인덱스로 필터링 결과 : {array3}")
불린 인덱스로 필터링 결과 : [6 7 8 9]
indexes = np.array([5,6,7,8])
array4 = array1d[indexes]
print(f"일반 인덱스로 필터링 결과: {array4}")
일반 인덱스로 필터링 결과: [6 7 8 9]

7. 행렬의 정렬 - sort( )와 argsort( )

  • np.sort( )의 경우 원 행렬은 그대로 유지한 채 원 행렬의 정렬된 행렬을 반환
  • ndarray.sort( )는 원 행렬 자체를 정렬한 형태로 변환하며 반환 값은 None
org_array = np.array([3, 1, 9, 5])
print(f"원본 행렬: {org_array}")

# np.sort( )로 정렬
sort_array1 = np.sort(org_array)
print(f"np.sort() 호출 후 반환된 정렬 행렬: {sort_array1}")
print(f"np.sort() 호출 후 원본 행렬: {org_array}")

# ndarray.sort( )로 정렬
sort_array2 = org_array.sort()
print(f"np.sort() 호출 후 반환된 정렬 행렬: {sort_array2}")
print(f"np.sort() 호출 후 원본 행렬: {org_array}")
원본 행렬: [3 1 9 5]
np.sort() 호출 후 반환된 정렬 행렬: [1 3 5 9]
np.sort() 호출 후 원본 행렬: [3 1 9 5]
np.sort() 호출 후 반환된 정렬 행렬: None
np.sort() 호출 후 원본 행렬: [1 3 5 9]
# 내림차순 정렬 [::-1]
sort_array1_desc = np.sort(org_array)[::-1]
print(f"내림차순으로 정렬: {sort_array1_desc}")
내림차순으로 정렬: [9 5 3 1]
  • 2차원 정렬
array2d = np.array([[8,12],
                   [7,1]])

sort_array2d_axis0 = np.sort(array2d, axis = 0)
print(f"로우 방향으로 정렬:\n {sort_array2d_axis0}")

sort_array2d_axis1 = np.sort(array2d, axis = 1)
print(f"칼럼 방향으로 정렬:\n {sort_array2d_axis1}")
로우 방향으로 정렬:
 [[ 7  1]
 [ 8 12]]
칼럼 방향으로 정렬:
 [[ 8 12]
 [ 1  7]]
  • 정렬된 행렬의 인덱스 반환하기
org_array = np.array([3,1,9,5])
sort_indices = np.argsort(org_array)
print(type(sort_indices))
print(f'행렬 정렬 시 원본 행렬의 인덱스: {sort_indices}')
<class 'numpy.ndarray'>
행렬 정렬 시 원본 행렬의 인덱스: [1 0 3 2]
org_array = np.array([3,1,9,5])
sort_indices_desc = np.argsort(org_array)[::-1] # 내림차순 정렬
print(f"행렬 내림차순 정렬 시 원본 행렬의 인덱스: {sort_indices_desc}")
행렬 내림차순 정렬 시 원본 행렬의 인덱스: [2 3 0 1]

8. 선형대수 연산 - 행렬 내적과 전치 행렬 구하기

  • 행렬 내적(행렬 곱) : np.dot()
A = np.array([[1,2,3],
             [4,5,6]])

B = np.array([[7,8],
             [9,10],
             [11,12]])
Multi_result = np.dot(A,B)
print(f"행렬 내적 결과 : \n {Multi_result}")
행렬 내적 결과 : 
 [[ 58  64]
 [139 154]]
  • 전치 행렬 : 원 행렬에서 행, 열 위치를 교환한 원소로 구성한 행렬
A = np.array([[1,2],
             [3,4]])
transpose_array = np.transpose(A)
print(f"A의 전치 행렬: \n {transpose_array}")
A의 전치 행렬: 
 [[1 3]
 [2 4]]

참고 파이썬 머신러닝 완벽 가이드