본문 바로가기

Data Scientist

넘파이 한번에 정리하기

반응형

 

 

나동빈 님, 파이썬 머신러닝 완벽 가이드 기반으로 작성했습니다.

 

Numerical Python: Numpy

pip install numpy
#또는
conda install numpy

import numpy as np

 기반 데이터 타입은 naddray이다. 

# Numpy의 차원 < 차원은 괄호로 판단한다. [ ]: 1차원 [[ ]]: 2차원 ... >

  • 1차원 축(행): axis 0 -> Vector

  • 2차원 축(열): axis 1 -> Matrix

  • 3차원 축(채널): axis 2 -> Tensor(3차원 이상)

array_int = np.array([1,2,3])
array_float = array_int.astype('float64')
array_float_int = array_float.astype('int32')
print('array_int:', array_int)
print('array_float:', array_float)
print('array_float_int:', array_float_int)
print('array_int shape:', array_int.shape)

================================================

array_int: [1 2 3]
array_float: [1. 2. 3.]
array_float_int: [1 2 3]
array_int shape: (3,)

 

array() 함수는 파이썬의 리스트와 같은 다양한 인자를 입력 받아서 ndarray로 변환하는 기능을 수행한다. 

생성된 ndarray 배열의 shape변수는 ndarray의 크기, 즉 행과 열의 수를 튜플 형태로 가지고 있으며

이를 통해 배열의 차원까지 알 수 있다. 

 

위에 입력한 int는 파이썬의 리스트 형태로 [1, 2, 3]을 가져와서 ndarray 형태로 만들었다. 

출력을 보면 알 수 있지만 [1 2 3]으로 scalar면서 기본 형태인 'int32'로 출력되었다. 

만약 형태를 바꾸고 싶다면 사용하는 것이 .astype() 함수이다. 

이 함수를 이용해서 실수(float)인지 정수(int)인지를 변경할 수 있으며 실수일 경우

연산이 더 느려지기 때문에 빠른 계산을 위해 정수로 변경해주는 경우도 있다. 

배열의 형태를 확인하려면 shape을 사용하며 튜플 속에 3, 으로 출력된 것을 알 수 있다. 

 

a = np.arange((10),dtype = 'float64')
b = a.reshape(2,5).astype('float64')
c = np.array([[1,2,3],[2,3,4],[5,6,7]])

print(a)
print('a_shape:', a.shape)
print('a_type:', type(a))
print('a_dtype:', a.dtype)
print('a_size', a.size)
print('a_index[2]:', a[2])
print()
print(b)
print('b_shape:', b.shape)
print('b_type:', type(b))
print('b_dtype:', b.dtype)
print('b_size', b.size)
print()
print(c)
print('c_shape', c.shape)
print('c_type', type(c))
print('c_dtype:', c.dtype)
print('c_size', c.size)
===========================================================

[0. 1. 2. 3. 4. 5. 6. 7. 8. 9.]
a_shape: (10,)
a_type: <class 'numpy.ndarray'>
a_dtype: float64
a_size 10
a_index[2]: 2.0

[[0. 1. 2. 3. 4.]
 [5. 6. 7. 8. 9.]]
b_shape: (2, 5)
b_type: <class 'numpy.ndarray'>
b_dtype: float64
b_size 10

[[1 2 3]
 [2 3 4]
 [5 6 7]]
c_shape (3, 3)
c_type <class 'numpy.ndarray'>
c_dtype: int32
c_size 9
['0.0' '1.0' '2.0' '3.0' '4.0' '5.0' '6.0' '7.0' '8.0' '9.0']
d_shape (10,)
d_type <class 'numpy.ndarray'>
d_dtype: <U32
d_size 10

 

type을 설정해주는 데는 dtypeastype이 있다. a와 b의 경우 각각 float 64로 설정해줬으며, 

c의 경우 그냥 출력(기본이 int32)되게 해주었다. 

그래서 출력을 해보면 각각의 형태, type과 dtype, 크기처럼 정보들이 출력된다. 

c의 경우 앞서 설명한 대로 괄호가 2개로 이루어져 있어 2차원 매트릭스(3x3)인 것을 알 수 있다. 

d는 a를 받아서 문자열 형태로도 출력이 가능한지 확인하기 위해 출력했다. 

잘 출력이 되지만 한번에 배열을 생성하면서 문자열을 쓰려면 에러가 난다. (하지만 ones, zeros에선 동작한다)

 

# 3x2형태로 0으로 이루어진 배열 생성
zero_array = np.zeros((3,2),  dtype='int32')
print(zero_array)
print(zero_array.dtype, zero_array.shape)

# 3x2형태로 1로 이루어진 배열 생성
one_array=np.ones((3,2), dtype='int32')
print(one_array)
print(one_array.dtype, one_array.shape)

# 0 부터 100까지 랜덤하게 3x3 형태로 배열 생성 
random_array = np.random.randint(0,100, (3,3), dtype = 'int32')
print(random_array)

# 평균이 0이고, 표준편차가 1인 표준 정규를 띄는 배열
norm_dist_array = np.random.normal(0,1, (3,3))
print(norm_dist_array)

===================================================================

[[0 0]
 [0 0]
 [0 0]]
int32 (3, 2)

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

[[22 18  0]
 [24 13  7]
 [49  6  9]]

[[-1.00212846  0.21637133 -0.82146145]
 [-0.585935    1.16831034  0.0636745 ]
 [-0.47722764 -1.68609583  0.58833812]]

 

 

# 균일한 간격으로 데이터 생성
array = np.linspace(0, 10, 5) 
array #0부터 10까지 사이의 5개의 데이터가 채우는 형태
------------------------------------------------------
array([ 0. ,  2.5,  5. ,  7.5, 10. ])
======================================================

# 난수의 재연(실행마다 결과 동일)
np.random.seed(7)   #7번에 해당하는 배열이 재연됨
print(np.random.randint(0, 10, (2,3)))
------------------------------------------------------
[[4 9 6]
 [3 3 7]]
======================================================

# Numpy 배열 객체 복사
array1 = np.arange(0,10)
array2 = array1   # 주소가 같기 때문에 array2를 수정해도 array1이 바뀜
array2[0] = 99
print(array1)
array1 = np.arange(0,10)
array2 = array1.copy()
print(array2)
------------------------------------------------------
[99  1  2  3  4  5  6  7  8  9]
[0 1 2 3 4 5 6 7 8 9]
======================================================

# 중복된 원소 제거
array = np.array([1, 1, 2, 3, 3, 3, 1])
print(np.unique(array))
------------------------------------------------------
[1 2 3]

 

 

sequence_array = np.arange(10)
print(sequence_array)
a = sequence_array.reshape(2,5)
a

======================================

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

 

reshape을 이용하면 원하는 형태로 차원과 크기를 변경할 수 있다. 여기선 물론 크기가 맞아야 한다.

10개의 데이터가 들어 있는데, 4x2형태의 매트릭스를 만들려면 2개가 남기 때문에 안된다.

 

array1 = np.arange(10)
print(array1)
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)

 

array1은 1차원 ndarray로 0~9까지 데이터를 갖고 있다. 

array2는 행이 -1이고 열이 5인데, 이는 array1과 호환될 수 있는 2차원 ndarray로 변환하되, 고정된 5개의 열에 맞는 행을 자동으로 새롭게 생성해 변환하라는 의미이다.

즉, 10개의 1차원 데이터와 호환될 수 있는 고정된 5개 열에 맞는 행의 개수는 2이므로 2x5의 2차원 ndarray로 변환하는 것이다. 

array3도 마찬가지로 고정된 행 5에 맞는 값인 2 열로, 5x2의 2차원 ndarray로 변환하는 것이다. 

 

array1 = np.arange(8)
array3d = array1.reshape((2,2,2))
print(array1)
print('array3d:\n', array3d)
print('array3d:\n', array3d.tolist())

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

#1차원 ndarray를 2차원 ndarray로 변환
array6 = array1.reshape(-1,1)
print('array6:\n', array6.tolist())
print('array6shape:', array6.shape)

============================================

[0 1 2 3 4 5 6 7]
array3d:
 [[[0 1]
  [2 3]]

 [[4 5]
  [6 7]]]
array3d:
 [[[0, 1], [2, 3]], [[4, 5], [6, 7]]]
 
 -------------------------------------------
 
 array5:
 [[0]
 [1]
 [2]
 [3]
 [4]
 [5]
 [6]
 [7]]
array5:
 [[0], [1], [2], [3], [4], [5], [6], [7]]
 
 -------------------------------------------
 
 array6:
 [[0], [1], [2], [3], [4], [5], [6], [7]]
array6shape: (8, 1)

 

 

reshape(-1, 1)은 원래 형태가 어떤 형태라도 2차원이면서 반드시 1개의 열을 가진 ndarray로 변환되게 한다. 

이 코드는 3차원 -> 2차원, 1차원 -> 2차원으로 변경된 것이며,

tolist() 메소드를 사용해서 리스트 자료형으로 변환 출력하였다. 

array1은 1차원으로 scalar들이다. 이를 이용해서 3차원으로 변환한 것이 array3d이다. 

array3d는 2x2형태가 2 덩어리가 있는 것을 알 수 있는데 이것이 2x2x2 형태이다. 

array5는 array3d를 2차원으로 변환시켜주었다. 

array6는 scalar를 2차원으로 만들어서 8x1 매트릭스로 변환되었다는 것을 알 수 있다. 

출력된 형태가 1x8이라 읭? 할 수 있지만 tolist 메소드를 사용했기 때문이고 원래는 array5처럼 출력된다.

 

 

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

1. 특정한 데이터만 추출: 원하는 위치의 인덱스 값을 지정하면 해당 위치의 데이터가 반환된다.

2. 슬라이싱(Slicing): 슬라이싱은 연속된 인덱스상의 ndarray를 추출하는 방식이다. '시작 : 종료' 로 표시하며

1:5라고 하면 1인덱스부터 4인덱스까지의 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)
array2 = np.arange(start=1, stop=10,step=2)
print(array1)
print(array2)
print('array1_third:', array1[2])
print('array2_third:', array2[2])
print('array1_last:',array1[-1])
print('array2_last:', array2[-1])
------------------------------------------------------------
# 2차원에서 특정 값 
array1d = np.arange(start=1,stop=10)
array2d = array1d.reshape(3,3)
print(array1d)
print(array2d)
print('(row=1, col=0) index가 가리키는 값:', array2d[1,0])
print('(row=1, col=2) index가 가리키는 값:', array2d[1,2])

=============================================================

[1 2 3 4 5 6 7 8 9]
[1 3 5 7 9]
array1_third: 3
array2_third: 5
array1_last: 9
array2_last: 9
--------------------------------------------------------------

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

 

 

array1 = np.arange(start=1, stop=10)
array3 = array1[0:3]
array4 = array1[:3]
array5 = array1[3:]
array6 = array1[:]

print(array3)
print(array4)
print(array5)
print(array6)
print('-'*30)
array2d = array1.reshape(3,3)
print('array2d:\n', array2d)
print('array2d[0:2, 0:2]\n', array2d[0:2, 0:2])
print('array2d[0:1, 1:2]\n', array2d[0:1, 1:2])
print('array2d[1:3, 1:2]\n', array2d[1:3, 1:2])


=====================================================

[1 2 3]
[1 2 3]
[4 5 6 7 8 9]
[1 2 3 4 5 6 7 8 9]
------------------------------
array2d:  #원래형태
 [[1 2 3]
 [4 5 6]
 [7 8 9]]
 
array2d[0:2, 0:2] # 0~1번째 행, 0~1번째 열 
 [[1 2]
 [4 5]]
 
array2d[0:1, 1:2] # 첫번째 행, 두번째 열
 [[2]]
 
array2d[1:3, 1:2] # 2~3번째 행, 2번째 열 
 [[5]
 [8]]

   

    2. 팬시 인덱싱(Fancy Indexing) 

리스트나 ndarray로 인덱스 집합을 지정하면 해당 위치의 인덱스에 해당하는 ndarray를 반환하는 인덱싱 방식이다. 

 

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

array3 = array2d[[0,1], 2]
array4 = array2d[[0,1], 0:2]
array5 = array2d[[0,1]]

print(array1d)
print(array2d)
print(array3)
print('array2d[[0, 1], 2] =>',array3.tolist())
print(array4)
print('array2d[[0, 1], 0:2] =>', array4.tolist())
print(array5)
print('array2d[[0, 1]] =>', array5.tolist())

====================================================
# array1d
[1 2 3 4 5 6 7 8 9]
# array2d
[[1 2 3]
 [4 5 6]
 [7 8 9]]
# array3
[3 6]
array2d[[0, 1], 2] => [3, 6]
# array4
[[1 2]
 [4 5]]
array2d[[0, 1], 0:2] => [[1, 2], [4, 5]]
# array5
[[1 2 3]
 [4 5 6]]
array2d[[0, 1]] => [[1, 2, 3], [4, 5, 6]]

 

이름이 왜 fancy인지는 모르겠지만.. 행과 열에 원하는 인덱스를 넣어서 출력하는 방식이다.

array2d[ [0,1], 2 ]의 경우 행에 팬시 인덱싱인 [0,1]을, 열에는 단일 값 인덱싱 2를 적용했다. 

따라서 (row,col) 인덱스가 (0,2), (1,2)로 적용<여기서는 첫번째 행 두번째, 첫번째 행 두번째>되어 [3,6]을 반환한다. 

 

    3. 불린 인덱싱

조건 필터링과 검색을 동시에 할 수 있기 때문에 매우 자주 사용되는 인덱싱 방법이다. 

ex) 1차원 ndarray [1,2,3,4,5,6,7,8,9]에서 데이터값이 5보다 큰 데이터만 추출하려면??

>> for loop & if else문을 이용하여 출력하거나 불린 인덱싱을 이용한다.

 

a = [1,2,3,4,5,6,7,8,9]
box = []
for i in a:
  if i>5:
    box.append(i)
print(box)

array1d = np.arange(start=1, stop=10)
# [ ]안에 array1d > 5 boolean indexing을 적용
array3 = array1d[array1d > 5]
print('array1d > 5 불린 인덱싱 결과 값 :', array3)  

=====================================================

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

 

for 구문과 if구문을 혼합해서 사용할 경우에와 불린 인덱싱을 사용하는 경우 모두 써보았다. 

사실 파이썬도 공부 중이지만 아직 많이 미숙해서 리스트 안에 나오게 하는 데 애를 먹었다...

미리 box라는 비어있는 리스트를 만들어주고 for구문으로 하나씩 뽑아줘서 박스에 추가해준다.

 

그리고 불린 인덱싱은 인덱싱에 조건을 주는 방법인데 이게 훨씬 간단하단 것을 확인할 수 있다! 

 

 

print(array1d)
a = array1d>5
print(a)
boolean_indexes = np.array(a)
array3 = array1d[boolean_indexes]
print('불린 인덱스로 필터링한 결과:', array3)

indexes = np.array([5,6,7,8])
array4 = array1d[indexes]
print('일반 인덱스로 필터링한 결과:', array4)

==============================================

[1 2 3 4 5 6 7 8 9] # array1d
[False False False False False  True  True  True  True] # array1d>5
불린 인덱스로 필터링한 결과: [6 7 8 9] # array3
일반 인덱스로 필터링한 결과: [6 7 8 9] # 인덱스 [5,6,7,8]의 결과값

 

조건을 주어서 5보다 크다면 True, 아니면 False로 반환하도록 한 뒤 True 값에 해당하는 위치 인덱스만 반환한다.

0~4는 무시하고 인덱스 [5,6,7,8]이 만들어지고 이는 데이터셋 [6,7,8,9]를 반환하게 된다.

불린 인덱싱은 내부적으로 여러 단계를 거쳐서 동작하지만, 코드 자체는 단순하므로 비교적 쉽게 코딩할 수 있다고 한다.

 

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

넘파이에서 행렬을 정렬하는 대표적인 방법인 np.sort( )와 ndarray.sort( ), 그리고 정렬된 행렬의 인덱스를

반환하는 argsort( )에 대해서 알아봐야 겠다.

 

- 행렬 정렬

np.sort( ): 넘파이에서 호출하는 방식
ndarray.sort( ): 행렬 자체에서 sort( )를 호출하는 방식 

두 방식의 차이는 np.sort( )의 경우 원 행렬은 그대로 유지한 채 원 행렬의 정렬된 행렬을 반환

ndarray.sort( )는 원 행렬 자체를 정렬한 형태로 변환하며 반환값은 None이다. 

 

org_array = np.array([3,1,9,5])
print('원본 행렬:', org_array)
#np.sort( )로 정렬
sort_array1 = np.sort(org_array)
print('np.sort( ) 호출 후 반환된 정렬 행렬:', sort_array1)
print('np.sort( ) 호출 후 반환된 원본 행렬:', org_array)

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

==================================================================

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

 

원본이 바꿀 것인지 아닌지에 따라서 np.sort( )와 행렬array.sort( ) 를 선택해서 사용한다. 

두 방식 모두 오름차순이 기본이며, 내림차순으로 정렬하기 위해서는 np.sort( )[::-1]을 사용한다. 

 

sort_array1_desc = np.sort(org_array)[::-1]
print('내림차순으로 정렬해보자:', sort_array1_desc)
====================================================
내림차순으로 정렬해보자: [9 5 3 1]

 

행렬이 2차원 이상일 경우에 axis 축 값 설정을 통해 로우 방향, 또는 칼럼 방향으로 정렬을 수행할 수 있다.

 

array2d = np.array([[8,12],[7,1]])
print(array2d)
sort_array2d_axis0 = np.sort(array2d, axis=0)
print('row 방향으로 정렬:\n', sort_array2d_axis0)
sort_array2d_axis1 = np.sort(array2d, axis=1)
print('col 방향으로 정렬:\n', sort_array2d_axis1)

===================================================

[[ 8 12]
 [ 7  1]]
row 방향으로 정렬:
 [[ 7  1]
 [ 8 12]]
col 방향으로 정렬:
 [[ 8 12]
 [ 1  7]]

 

사진처럼 행 기준 정렬이면 세로로 된 것들 중에 큰 값이 아래로 가는 오름차순 정렬이 실행된다. 

마찬가지로 열 기준이면 가로로 된 값들 중에 작은 값이 앞으로 오게 된다. 

 

 

- 정렬된 행렬의 인덱스를 반환하기

원본 행렬을 정렬해 보았을 때 기존 원본 행렬의 원소에 대한 인덱스를 필요로 하다면, 이 때 np.argsort( )를 이용한다. 

np.argsort( )는 정렬 행렬의 원본 행렬 인덱스를 ndarray 형으로 반환한다. 

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

[3 1 9 5]
<class 'numpy.ndarray'>
행렬 오름차순 정렬 시 원본 행렬의 인덱스: [1 0 3 2]
행렬 내림차순 정렬 시 원본 행렬의 인덱스: [2 3 0 1]

 

org_array가 [3 1 9 5]로 배열되어 있는데 기본 정렬인 오름차순으로 정렬하면 [1 3 5 9]가 되게 된다. 

[1 3 5 9]는 원본 자료의 인덱스 기준으로 [1 0 3 2]로 정렬된 것이다.

내림차순의 경우 [9 5 3 1]이 되므로 [2 3 0 1]로 출력된다. 

 

argsort( ) 는 넘파이에서 활용도가 매우 높다고 한다. 넘파이의 ndarray는 RDBMS(Relational DataBase Management System,관계형 데이터베이스 관리 시스템)의 TABLE 칼럼이나 판다스 DataFrame 칼럼과 같은 메타 데이터(데이터에 대한 데이터?? 꿈속의 꿈..??)를 가질 수 없다. 따라서 실제 값과 그 값이 뜻하는 메타 데이터를 별도의 ndarray로 각각 가져야만 한다. 
예를 들어 학생별 시험 성적을 데이터로 표현하기 위해서는 학생의 이름과 시험 성적을 각각 ndarray로 가져야 한다.  즉, [철수 = 78, 워니=95, 노니=84, 후니=98]을 ndarray로 활용하고자 한다면 name_array=[철수, 워니, 노니, 후니]와 score_array=[78, 95, 84, 98]과 같이 2개의 ndarray를 만들어야 한다. 이 때 시험 성적순으로 학생 이름을 출력하고자 한다면 np.argsort(score_array)를 이용해 반환된 인덱스를 name_array에 팬시 인덱스로 적용해 추출할 수 있으며 이러한 방식은 넘파이의 데이터 추출에서 많이 사용된다!!!!!!!!!!!!!!!!!!!

 

name_array = np.array(['철수','워니','노니','후니'])
score_array = np.array([78, 95, 84, 98])
sort_indices_asc = np.argsort(score_array)
sort_indices_des = np.argsort(score_array)[::-1]
print('성적 오름차순 정렬 시 score_array의 인덱스:', sort_indices_asc)
print('성적 오름차순으로 name_array의 이름 출력:', name_array[sort_indices_asc])
print('성적 내림차순으로 name_array의 이름 출력:', name_array[sort_indices_des])

===================================================================================

성적 오름차순 정렬 시 score_array의 인덱스: [0 2 1 3]
성적 오름차순으로 name_array의 이름 출력: ['철수' '노니' '워니' '후니']
성적 내림차순으로 name_array의 이름 출력: ['후니' '워니' '노니' '철수']

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

- 행렬 내적(행렬 곱)

두 행렬 A와 B의 내적은 np.dot( )을 이용해 계산이 가능하다. 

행렬 계산은 고등학교? 중학교때 기초적으로 배우니까 다들 잘 아실 것 같다. 

(2x3) * (3*2) 행렬이고 *을 기준으로 마주 닿는 숫자가 같아야 계산이 가능하고 

결과값은 맨 앞과 맨뒤의 숫자인 (2x2)로 나온다는 것으로 어렴풋이 기억이 났다. 

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

 

A1 = np.random.randint(1, 100, (3,3))
B1 = np.arange(start=1, stop= 22, step = 4)
B2 = B1.reshape(3,2)
dot_product1 = np.dot(A1,B2)
print('A1:\n',A1)
print('B2:\n',B2)
print()
print('행렬 내적 결과:\n', dot_product1)

====================================================

A1:
 [[74 51 60]
 [15 21 95]
 [58  3  9]]
B2:
 [[ 1  5]
 [ 9 13]
 [17 21]]

행렬 내적 결과:
 [[1553 2293]
 [1819 2343]
 [ 238  518]]

- 전치 행렬

원 행렬에서 행과 열 위치를 교환한 원소로 구성한 행렬을 그 행렬의 전치 행렬이라고 한다. 

즉 2x2 행렬 A가 있을 경우 A 행렬의 1행 2열의 원소를 2행 1열의 원소로, 2행 1열의 원소를 1행 2열의

원소로 교환하는 것입니다. 이 때 행렬은 A의 전치 행렬은 A의 T승과 같이 나타낸다. 

 

A = np.array([[1,2],[3,4]])
transpose_mat = np.transpose(A)
print('A의 전치 행렬: \n', transpose_mat)

=========================================

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

 

선형대수학에서, 전치행렬(transposed matrix)은 행과 열을 교환하여 얻는 행렬이다. 

즉, 주 대각선을 축으로 하는 반사 대칭을 가하여 얻는 행렬이다. 

 

 

Numpy 배열 합치기 

a1 = np.array([1,2])
a2 = np.array([3,4])
a3 = np.concatenate([a1, a2])
print(a3.shape)
print(a3)

===============================

(4,)
[1 2 3 4]

- 배열 세로축으로 합치기 (array1 밑에 array2)

array1 = np.arange(4).reshape(1,4) #0부터 4까지 1x4
array2 = np.arange(8).reshape(2,4) #0부터 7까지 2x4
array3 = np.concatenate([array1, array2], axis=0)
print(array1)
print()
print(array2)
print()
print(array3)

=======================================================

[[0 1 2 3]]

[[0 1 2 3]
 [4 5 6 7]]

[[0 1 2 3]
 [0 1 2 3]
 [4 5 6 7]]

 

- 배열 나누기 

array = np.arange(8).reshape(2,4)
left, right = np.split(array, [2], axis = 1)

print(left.shape)
print(right.shape)
print(array)
print(left)
print(right)

================================================

(2, 2)  #left shape
(2, 2)  #right shape
[[0 1 2 3]   #array
 [4 5 6 7]]
[[0 1]  #array left side
 [4 5]] 
 
[[2 3]  #array right side
 [6 7]]

이런 식으로 인덱스 2를 기준으로 분할한다. 

 

- 상수 연산

a = np.random.randint(1, 10, size = 4).reshape(2,2)
print(a)
print('-'*30)
Sa = a+10
print(Sa)
print('-'*30)
Ma = a*10
print(Ma)

[[1 6]
 [6 5]]
------------------------------
[[11 16]
 [16 15]]
------------------------------
[[10 60]
 [60 50]]

- 서로 다른 형태의 Numpy 연산

array1 = np.arange(4).reshape(2,2)
array2 = np.arange(2)
array3 = array1 + array2
print(array1)
print()
print(array2)
print()
print(array3)

[[0 1]
 [2 3]]

[0 1]

[[0 2]
 [2 4]]

- 브로드캐스트 

형태가 다른 배열을 연산할 수 있도록 배열의 형태를 동적으로 변환

array1 = np.arange(0,8).reshape(2,4)     # 2x4
array2 = np.arange(0,8).reshape(2,4)     # 2x4
array3 = np.concatenate([array1,array2], axis=0)   #2x4 + 2x4 = 4x4
array4 = np.arange(0,4).reshape(4,1)   # 4x1 
print(array1)
print('-'*30)
print(array2)
print('-'*30)
print(array3)
print('-'*30)
print(array4)
print('-'*30)
print(array3 + array4) 

=============================================================================
[[0 1 2 3]
 [4 5 6 7]]
------------------------------
[[0 1 2 3]
 [4 5 6 7]]
------------------------------
[[0 1 2 3]
 [4 5 6 7]
 [0 1 2 3]
 [4 5 6 7]]
------------------------------
[[0]
 [1]
 [2]
 [3]]
------------------------------
[[ 0  1  2  3]
 [ 5  6  7  8]
 [ 2  3  4  5]
 [ 7  8  9 10]]

broadcasting

- 마스킹

각 원소에 대해서 True, False 체크해서 True에 해당하는 값에 작업을 시행. 

반복문을 이용할 때보다 매우 빠르게 동작하며 대체로 이미지 처리(Image Processing)에서 자주 활용된다.

array1 = np.arange(16).reshape(4,4)
print(array1)
print('-'*20)
array2 = array1 < 10
print(array2)
print('-'*20)
array1[array2] = 100
print(array1)

=======================================

[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]]
--------------------
[[ True  True  True  True]
 [ True  True  True  True]
 [ True  True False False]
 [False False False False]]
--------------------
[[100 100 100 100]
 [100 100 100 100]
 [100 100  10  11]
 [ 12  13  14  15]]

 

- 집계함수

array = np.arange(16).reshape(4,4)
print(array)
print('최대값:', np.max(array))
print('최소값:', np.min(array))
print('합계:', np.sum(array))
print('평균값:', np.mean(array))

====================================

[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]]
최대값: 15
최소값: 0
합계: 120
평균값: 7.5
# Numpy의 저장과 불러오기

#단일 객체 저장 및 불러오기
array = np.arange(0,10)
np.save('saved.npy', array)
result = np.load('saved.npy')
print(result)
-------------------------------
[0 1 2 3 4 5 6 7 8 9]

======================================================================================

# 복수 객체 저장 및 불러오기
array1 = np.arange(0,10)
array2 = np.arange(10,20)
np.savez('saved.npz', array1=array1, array2=array2) # 각각 객체 담을 수 있음
data = np.load('saved.npz') #저장할때 객체의 이름인덱스로 접근해서 불러올 수 있음
result1 = data['array1'] 
result2 = data['array2']
print(result1)
print(result2)
---------------------------------------------------------------------------------------
[0 1 2 3 4 5 6 7 8 9]
[10 11 12 13 14 15 16 17 18 19]

 

반응형

'Data Scientist' 카테고리의 다른 글

빅데이터를 지배하는 통계의 힘  (0) 2020.02.11
판다스 한번에 정리하기  (0) 2020.02.11
R기초  (0) 2020.02.07
기초통계 - 척도  (0) 2020.02.07
챗봇솔루션 closer를 이용한 나만의 챗봇 만들기!  (0) 2020.02.06