본문 바로가기

Machine Learning/머신러닝 완벽가이드 for Python

ch1.3 넘파이(실습)

1  Numpy ndarray 개요

 

  • ndarray 생성 np.array( )
import numpy as np

list1 = [1, 2, 3]
print("list1:", list1)
print("list1 type:", type(list1))

>>> list1: [1, 2, 3]
    list1 type: <class 'list'>
    
    
array1 = np.array(list1)
print("array1:", array1)
print("array1 type:", type(array1))


>>> array1: [1 2 3]
	array1 type: <class 'numpy.ndarray'>

 

 

  • ndarray 의 형태(shape)와 차원
# 1차원 ndarray
array1 = np.array([1,2,3])

print('array1 type:',type(array1))
print('array1 array 형태:',array1.shape)
print('array1 array 차원:',array1.ndim)
array1

>>> array1 type: <class 'numpy.ndarray'>
    array1 array 형태: (3,)
    array1 array 차원: 1
    array([1, 2, 3])
    
    
# 2차원 ndarray
array2 = np.array([[1,2,3],
                  [2,3,4]])

print('array2 type:',type(array2))
print('array2 array 형태:',array2.shape)
print('array2 array 차원:',array2.ndim)
array2

>>> array2 type: <class 'numpy.ndarray'>
    array2 array 형태: (2, 3)
    array2 array 차원: 2
    array([[1, 2, 3],
           [2, 3, 4]])
           
           
# 2차원 ndarray(행이 1개만 있는 2차원)
array3 = np.array([[1,2,3]])

print('array3 type:', type(array3))
print('array3 array 형태:', array3.shape)
print('array3 array 차원:',array3.ndim)
array3

>>> array3 type: <class 'numpy.ndarray'>
    array3 array 형태: (1, 3)
    array3 array 차원: 2
    array([[1, 2, 3]])
    
    
print('array1: {:0}차원, array2: {:1}차원, array3: {:2}차원'.format(array1.ndim,array2.ndim,array3.ndim))

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

 

 

  • ndarray 데이터 값 타입
list1 = [1,2,3]
print(type(list1))

>>> <class 'list'>

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

>>> <class 'numpy.ndarray'>
    [1 2 3] int32
    

list2 = [1, 2, 'test']
array2 = np.array(list2)
print(array2, array2.dtype)

>>> ['1' '2' 'test'] <U11 # <U11은 문자열 타입의 종류


# float 형태로 변환
array_int = np.array([1, 2, 3])
array_float = array_int.astype('float64')
print(array_float, array_float.dtype)

>>> [1. 2. 3.] float64


# int 형태로 변환
array_int1= array_float.astype('int32')
print(array_int1, array_int1.dtype)

>>> [1 2 3] int32

# int 형태로 변환
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] int32

 

 

  • ndarray에서 axis 기반의 연산함수 수행
array2 = np.array([[1,2,3],
                  [2,3,4]])

print("전체 합: ", array2.sum())
print("axis0 합: ", array2.sum(axis=0)) # 행의합
print("axis1 합: ", array2.sum(axis=1)) # 열의합

>>> 전체 합:  15
    axis0 합:  [3 5 7]
    axis1 합:  [6 9]

 

 

2  넘파이 배열 ndarray 생성, reshape()

 

  • ndarray를 편리하게 생성하기 - arange, zeros, ones
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,)
    
    
# zeros 0을 가진 행열을 만들어라

zero_array = np.zeros((3,2))
print(zero_array)
print(zero_array.dtype, zero_array.shape)

>>> [[0. 0.]
     [0. 0.]
     [0. 0.]]
    float64 (3, 2)
    
# 1을 가진 행열을 만들어라

one_array = np.ones((3,2), dtype='int32')
print(one_array)
print(one_array.dtype, one_array.shape)

>>> [[1 1]
     [1 1]
     [1 1]]
    int32 (3, 2)

 

 

  • ndarray의 shape를 변경하는 reshape()
# 변경할때 2x5 = 10 즉, 10이 나오도록 바꾸어야 한다

array1 = np.arange(10)
print('array1:\n', array1)

array2 = array1.reshape(2,5)
print('array2:\n',array2)

array3 = array1.reshape(5,2)
print('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]]
# 변환할 수 없는 shape구조를 입력하면 오류 발생.
array1.reshape(4,3) # 10 -> 12 오류!

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Input In [21], in <cell line: 2>()
      1 # 변환할 수 없는 shape구조를 입력하면 오류 발생.
----> 2 array1.reshape(4,3)

ValueError: cannot reshape array of size 10 into shape (4,3)

 

 

reshape()에 -1 인자값을 부여하여 특정 차원으로 고정된 가변적인 ndarray형태 변환

 

array1 = np.arange(10) 
print(array1)

>>> [0 1 2 3 4 5 6 7 8 9]

# 컬럼 axis 크기는 5에 고정하고 로우 axis크기를 이에 맞춰 자동으로 변환. 
# 즉 2x5 형태로 변환 
# 즉, 내가 5라고 쓰면 그에 맞는 수를 -1 자리에 대입해져 있다.

array2 = array1.reshape(-1,5)
print('array2 shape:',array2.shape)
print('array2:\n', array2)

>>> array2 shape: (2, 5)
    array2:
     [[0 1 2 3 4]
     [5 6 7 8 9]]
     
# 로우 axis 크기는 5로 고정하고 컬럼 axis크기는 이에 맞춰 자동으로 변환. 
# 즉 5x2 형태로 변환 
array3 = array1.reshape(5,-1)
print('array3 shape:',array3.shape)
print('array3:\n', array3)

>>> array3 shape: (5, 2)
    array3:
     [[0 1]
     [2 3]
     [4 5]
     [6 7]
     [8 9]]
     
# reshape()는 (-1, 1), (-1,)와 같은 형태로 주로 사용됨.
# 1차원 ndarray를 2차원으로 또는 2차원 ndarray를 1차원으로 변환 시 사용. 
array1 = np.arange(5)
array1

>>> array([0, 1, 2, 3, 4])


# 1차원 ndarray를 2차원으로 변환하되, 컬럼axis크기는 반드시 1이여야 함. 
array2d_1 = array1.reshape(-1, 1)
print("array2d_1 shape:", array2d_1.shape)
print("array2d_1:\n",array2d_1)

>>> array2d_1 shape: (5, 1)
    array2d_1:
     [[0]
     [1]
     [2]
     [3]
     [4]]
     
     
 # 2차원 ndarray를 1차원으로 변환 
array1d = array2d_1.reshape(-1,)
print("array1d shape:", array1d.shape)
print("array1d:\n",array1d)

>>> array1d shape: (5,)
    array1d:
     [0 1 2 3 4]
     
     
# -1 을 적용하여도 변환이 불가능한 형태로의 변환을 요구할 경우 오류 발생.
array1 = np.arange(10)
array4 = array1.reshape(-1, 4)

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Input In [31], in <cell line: 3>()
      1 # -1 을 적용하여도 변환이 불가능한 형태로의 변환을 요구할 경우 오류 발생.
      2 array1 = np.arange(10)
----> 3 array4 = array1.reshape(-1, 4)

ValueError: cannot reshape array of size 10 into shape (4)


# 반드시 -1 값은 1개의 인자만 입력해야 함. 
array1.reshape(-1, -1)

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Input In [32], in <cell line: 2>()
      1 # 반드시 -1 값은 1개의 인자만 입력해야 함. 
----> 2 array1.reshape(-1, -1)

ValueError: can only specify one unknown dimension

 

 

3  ndarray의 데이터 세트 선택하기 – 인덱싱(Indexing)

 

특정 위치의 단일값 추출

 

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

>>>  array1: [1 2 3 4 5 6 7 8 9]


# index는 0 부터 시작하므로 array1[2]는 3번째 index 위치의 데이터 값을 의미
value = array1[2]
print('value:',value)
print(type(value))

>>> value: 3
    <class 'numpy.int32'>
    
    
print('맨 뒤의 값:', array1[-1], ', 맨 뒤에서 두번째 값:', array1[-2])

>>> 맨 뒤의 값: 9 , 맨 뒤에서 두번째 값: 8


# 요소 수정
array1[0] = 9
array1[8] = 0
print('array1:',array1)

>>> array1: [9 2 3 4 5 6 7 8 0]


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

>>> <class 'numpy.ndarray'>
    [[1 2 3]
     [4 5 6]
     [7 8 9]]
     

print('(row=0,col=0) index 가리키는 값:', array2d[0, 0] )
print('(row=0,col=1) index 가리키는 값:', array2d[0, 1] )
print('(row=1,col=0) index 가리키는 값:', array2d[1, 0] )
print('(row=2,col=2) index 가리키는 값:', array2d[2, 2] )

>>> (row=0,col=0) index 가리키는 값: 1
    (row=0,col=1) index 가리키는 값: 2
    (row=1,col=0) index 가리키는 값: 4
    (row=2,col=2) index 가리키는 값: 9

 

 

 

슬라이싱(Slicing)

 

 

연속적인 데이터 가져오기

 

array1 = np.arange(start=1, stop=10)
print(array1)

>>> [1 2 3 4 5 6 7 8 9]


array3 = array1[0:3]
print(type(array3))
print(array3)

>>> <class 'numpy.ndarray'>
	[1 2 3]
    
    
array1 = np.arange(start=1, stop=10)
array1

>>> array([1, 2, 3, 4, 5, 6, 7, 8, 9])


array4 = array1[:3]
print(array4)

>>> [1 2 3]


array5 = array1[3:]
print(array5)

>>> [4 5 6 7 8 9]


array6 = array1[:]
print(array6)

>>> [1 2 3 4 5 6 7 8 9]


array1d = np.arange(start=1, stop=10)
array1d

>>> array([1, 2, 3, 4, 5, 6, 7, 8, 9])

array2d = array1d.reshape(3, 3)
print('array2d:\n',array2d)

>>> array2d:
     [[1 2 3]
     [4 5 6]
     [7 8 9]]

print('array2d[0:2, 0:2] \n', array2d[0:2, 0:2]) # array2d [행, 열]
print('array2d[1:3, 0:3] \n', array2d[1:3, 0:3])
print('array2d[1:3, :] \n', array2d[1:3, :])
print('array2d[:, :] \n', array2d[:, :])
print('array2d[:2, 1:] \n', array2d[:2, 1:])
print('array2d[:2, 0] \n', array2d[:2, 0])

>>> 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]

 

 

 

 

팬시 인덱싱(fancy indexing)

 

비연속적인 데이터 인덱싱

 

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

>>> [[1 2 3]
     [4 5 6]
     [7 8 9]]
     
     
array3 = array2d[[0, 1], 2]
array3

>>> array([3, 6])


list(array3)

>>> [3, 6]

array4 = array2d[[0,2], 0:2]
array4

>>> array([[1, 2],
           [7, 8]])
       
list(array4)

>>> [array([1, 2]), array([7, 8])]


array5 = array2d[[0, 1]]
array5

>>> array([[1, 2, 3],
           [4, 5, 6]])
           
array5.tolist()

>>> [[1, 2, 3], [4, 5, 6]]

 

 

불린 인덱싱(Boolean indexing)

 

array1d = np.arange(start=1, stop=10)
print(array1d)

>>> [1 2 3 4 5 6 7 8 9]

var1 = array1d > 5
print(var1)
print(type(var1))

>>> [False False False False False  True  True  True  True]
	<class 'numpy.ndarray'>	
    
    
print(array1d)

>>> [1 2 3 4 5 6 7 8 9]


# [ ] 안에 array1d > 5 Boolean indexing을 적용 

array3 = array1d[array1d > 5]
print('array1d > 5 불린 인덱싱 결과 값 :', array3)

>>> array1d > 5 불린 인덱싱 결과 값 : [6 7 8 9]

boolean_indexes = np.array([False, False, False, False, False,  True,  True,  True,  True])
boolean_indexes

>>> array([False, False, False, False, False,  True,  True,  True,  True])


array3 = array1d[boolean_indexes]
print('불린 인덱스로 필터링 결과 :', array3)

>>> 불린 인덱스로 필터링 결과 : [6 7 8 9]


indexes = np.array([5, 6, 7, 8])
indexes

>>> array([5, 6, 7, 8])


# 팬시 인덱싱 (원하는 위치 값들로 인덱싱)
array4 = array1d[indexes]
print('일반 인덱스로 필터링 결과 :', array4)

>>> 일반 인덱스로 필터링 결과 : [6 7 8 9]

array1d = np.arange(start=1, stop=10)
array1d

>>> array([1, 2, 3, 4, 5, 6, 7, 8, 9])


# 6,7,8,9를 뽑을때, 불린 인덱싱을 모를때 
target = []

for i in range(0, 9):
    if array1d[i] > 5:
        target.append(array1d[i])

array_selected = np.array(target)

>>> [6 7 8 9]


# 위 코드를 간단한 불린 인덱싱으로 해결할 수 있다.

print(array1d[array1 > 5])
>>> [6 7 8 9]

 

4  행렬의 정렬 – sort( )와 argsort( )

 

4.1  sort()

org_array = np.array([ 3, 1, 9, 5])
print('원본 행렬:', org_array)

>>> 원본 행렬: [3 1 9 5]

# np.sort( )로 정렬 : 객체 자체(org_array)는 변경되지 않음
# 객체 자체를 변경하지 않기 때문에 변수저장을 해야한다.
sort_array1 = np.sort(org_array)

print ('np.sort( ) 호출 후 반환된 정렬 행렬:', sort_array1) 
print('np.sort( ) 호출 후 원본 행렬:', org_array)

>>> np.sort( ) 호출 후 반환된 정렬 행렬: [1 3 5 9]
	np.sort( ) 호출 후 원본 행렬: [3 1 9 5]
    
    
# ndarray.sort( )로 정렬 : 객체 자체(org_array)를 변경함
# 원본 자체가 바뀌었기 때문에 None이 나온다.
sort_array2 = org_array.sort()

print('org_array.sort( ) 호출 후 반환된 행렬:', sort_array2)
print('org_array.sort( ) 호출 후 원본 행렬:', org_array)

>>> org_array.sort( ) 호출 후 반환된 행렬: None
	org_array.sort( ) 호출 후 원본 행렬: [1 3 5 9]
    

# np.sort( )로 내림차순 정렬
# ::은 간격, -1 은 역으로, 역 간격으로 내림차순하여라 라는 의미
sort_array1_desc = np.sort(org_array)[::-1]
print ('내림차순으로 정렬:', sort_array1_desc) 

내림차순으로 정렬: [9 5 3 1]

 

 

4.2  2차원 행렬 정렬

array2d = np.array([[8, 12],
                    [7, 1 ]])
array2d

>>> array([[ 8, 12],
       [ 7,  1]])
       
# axis를 기준을 정렬한다. axis = 0 행기준으로 정렬 
sort_array2d_axis0 = np.sort(array2d, axis=0)
print('로우 방향으로 정렬:\n', sort_array2d_axis0)

# axis를 기준을 정렬한다. axis = 0 열기준으로 정렬 
sort_array2d_axis1 = np.sort(array2d, axis=1)
print('컬럼 방향으로 정렬:\n', sort_array2d_axis1)


>>> 로우 방향으로 정렬:
     [[ 7  1]
     [ 8 12]]
    컬럼 방향으로 정렬:
     [[ 8 12]
     [ 1  7]]

 

 

4.3  argsort()

# argsort() 랭킹의 인덱스를 뽑고 싶다!

org_array = np.array([ 3, 1, 9, 5]) 
print(np.sort(org_array))

>>> [1 3 5 9]


sort_indices = np.argsort(org_array)
print(type(sort_indices))
print('행렬 정렬 시 원본 행렬의 인덱스:', sort_indices)

>>> <class 'numpy.ndarray'>
    행렬 정렬 시 원본 행렬의 인덱스: [1 0 3 2]
    
org_array = np.array([ 3, 1, 9, 5]) 
print(np.sort(org_array)[::-1])

>>> [9 5 3 1]


sort_indices_desc = np.argsort(org_array)[::-1]
print('행렬 내림차순 정렬 시 원본 행렬의 인덱스:', sort_indices_desc)

>>> 행렬 내림차순 정렬 시 원본 행렬의 인덱스: [2 3 0 1]

 

 

 

Q. key-value 형태의 데이터 John=78, Mike=95, Sarah=84, Kate=98, Samuel=88 를
ndarray로 만들고 argsort()를 이용하여 key값을 정렬하여라.

 

name_array = np.array(['John', 'Mike', 'Sarah', 'Kate', 'Samuel'])
score_array = np.array([78, 95, 84, 98, 88])

-> score_array의 정렬된 값에 해당하는 원본 행렬 위치 인덱스 반환하고 
이를 이용하여name_array에서 name값 추출.

sort_indices = np.argsort(score_array)
print("sort indices:", sort_indices)

>>> sort indices: [0 2 4 1 3]

name_array_sort = name_array[sort_indices]
score_array_sort = score_array[sort_indices]

print(name_array_sort)
print(score_array_sort)

>>> ['John' 'Sarah' 'Samuel' 'Mike' 'Kate']
    [78 84 88 95 98]

 

 

5  선형대수 연산 – 행렬 내적과 전치 행렬 구하기

 

5.1  행렬 내적

A = np.array([[1, 2, 3],
              [4, 5, 6]])

# A (2,3)
B = np.array([[7, 8],
              [9, 10],
              [11, 12]])
# B (3,2)

# (2,3) X (3,2) = (2,2)

 

dot_product = np.dot(A, B)
print('행렬 내적 결과:\n', dot_product)

>>> 행렬 내적 결과:
     [[ 58  64]
     [139 154]]

 

 

5.2  전치 행렬

 

# 전치 = 행 <-> 열 변환
A = np.array([[1, 2],
              [3, 4]])

transpose_mat = np.transpose(A)
print('A의 전치 행렬:\n', transpose_mat)

>>> A의 전치 행렬:
     [[1 3]
     [2 4]]

 

'Machine Learning > 머신러닝 완벽가이드 for Python' 카테고리의 다른 글

ch.1.5 정리  (0) 2022.10.05
ch 1.4 판다스(실습)  (0) 2022.10.04
ch.1.4 판다스(이론)  (0) 2022.10.04
ch.1.3 넘파이(이론)  (0) 2022.10.04
인공지능/머신러닝/딥러닝 개괄(9/28)  (0) 2022.09.28