numpy

zzZ·2022년 7월 21일

NumPy는 행렬이나 일반적으로 대규모 다차원 배열을 쉽게 처리할 수 있도록 지원하는 파이썬의 라이브러리이다

  • 넘파이 array()함수는 파이썬의 리스트와 같은 다양한 인자를 입력받아서 ndarray로 변환하는 기능을 수행한다
  • ndarray의 shape변수는 ndarray의 크기, 즉 행과 열의 수를 튜플형태로 가지고 있고 차원까지 알 수 있다
import numpy as np
array1 = np.array([1, 2, 3])
array2 = np.array([[1, 2, 3],[4, 5, 6]])
array3 = np.array([[1,2,3]])print('array1 type: ', type(array1))
print('array1 형태: ', array1.shape)
print('array2 형태: ', array2.shape)
print('array3 형태: ', array3.shape)

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

  • ndarray.ndim으로 각 array의 차원을 확인할 수 있다
print('array1: {:0}차원, array2: {:1}차원, 
array3: {:2}차원'.format(array1.ndim, array2.ndim, array3.ndim))

ndarray 데이터 타입

  • ndarray의ㅣ 데이터 값은 숫자, 문자열, 불 값등 모두 가능하다
  • 그러나 한 개의 ndarray객체에 int와 float이 함께 있을 수 없다
  • 위의 숫자 1, 2 는 모두 문자열 값 '1', '2'로 변환됐다
list2 = [1, 2, 'test']
array2 = np.array(list2)
print(array2, array2.dtype)

['1' '2' 'test'] U11

  • astype()메소드로 데이터값의 타입 변경을 할 수 있다
array_int = np.array([1, 2, 3])
array_float = array_int.astype('float64')
print(array_float, array_float.dtype)

[1. 2. 3.] float64

ndarray를 편리하게 생성

1. arange()

  • arange()는 0부터 함수 인자 값 -1까지의 값을 순차적으로 ndarray의 데이터 값으로 반환해 준다

  • start, stop을 통해 연속한 값을 부여할 수 있다

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,)


2. zeros(), ones()

  • zeros()는 함수 인자로 튜플형태의 shape값을 입력하면 모든 값을 으로 채운 해당 shape를 가진 ndarray를 반환한다
  • ones()도 마찬가지
zero_array = np.zeros((3, 2), dtype='int32')
print(zero_array)

reshape()

  • reshape()메소드는 ndarray를 특정 차원 및 크기로 반환한다

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

reshape인자를 -1로

  • reshape()인자로 -1을 사용하면 원래 ndarray와 호환되는 새로운 shape로 반환해준다
 
array2 = array1.reshape(-1, 5)
array3 = array1.reshape(5, -1)

print(array2)
print(array3)

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

array2는 array1.reshape(-1, 5)로 로우 인자가 -1, 행 인자가 5이다 이것은 array1과 호환될 수 있는 2차원 ndarray로 변환하고 5개의 칼럼에 맞는 로우를 자동으로 생성하라는 의미이다

차원을 변환

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

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

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

arrayy3d:
[[[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)


넘파이 인덱싱(indexing)

단일 값 추출

import numpy as np

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

# index는 0부터 시작하므로 array1[2]는 3번째 index 위치의 데이터값을 의미

value = array1[2]

print('value:',value)
print(type(value))

array1: [1 2 3 4 5 6 7 8 9]
value: 3
<class 'numpy.int32'>

  • -1인자는 맨뒤의 인덱스를 의미한다
print('맨 뒤의 값:', array1[-1],' 맨 뒤의 값:', array1[-2])

맨 뒤의 값: 9 맨 뒤의 값: 8

  • 단일 인덱스를 이용해 ndarray 내의 데이터값도 간단히 수정 가능하다
array1[0] = 9
array1[8] = 0
print('array1:', array1)

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


다차원 ndarray에서 단일 값 추출

  • 콤마 (,)로 분리된 로우와 칼럼 위치의 인덱스를 접근한다
array1d = np.arange(start=1, stop=10)
array2d = array1d.reshape(3, 3)
print(array2d)

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

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

axis

  • axis0은 로우 방향 축을 의미한다
  • axis1은 칼럼 방향 축을 의미한다
  • [row=0, col=1] 인덱싱은 [axis 0=0, axis 1=1]이 맞는 표현이다
  • 3차원 ndarray의 axis 0, axis 1, axis 2로 3개의 축을 갖는다

슬라이싱

  • ':' 기호를 이용해 연속한 데이터를 슬라이싱해서 추출할 수 있다
array1 = np.arange(start=1,stop=10)
array3 = array1[0:3]
print(array3)
print(type(array3))

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

  1. ':' 기호 앞에 시작 인덱스를 생략하면 자동으로 맨 처음 인덱스인 0으로 간주한다
  2. ':' 기호 뒤에 종료 인덱스를 생략하면 자동으로 맨 마지막 인덱스로 간주한다
  3. ':' 기호 앞/뒤에 시작/종료 인덱스를 생략하면 자동으로 맨 처음/맨 마지막 인덱스로 간주한다

->2차원 ndarray인덱싱 예시

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

print('array2d[0:2, 0:2]\n', array2d[0:2, 0:2])
print('array2d[:, :]\n', array2d[:, :])
print('array2d[:2, 1:]\n', array2d[:2, 1:])

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


팬시 인덱싱

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

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

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

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

array5 = array2d[[0,1]]
print('array2d[[0, 1]] => ', array5.tolist())

array2d[[0,1], 2] => [3, 6]
array2d[[0,1], 0:2] [[1, 2], [4, 5]]
array2d[[0, 1]] => [[1, 2, 3], [4, 5, 6]]

불린 인덱싱

  • 불린 인덱싱은 조건 필터링과 검색을 동시에 할 수 있기 때문에 자주 사용되는 인덱싱 방식이다
# 불린 인덱싱
array1d = np.arange(start=1, stop=10)
array3 = array1d[array1d>5]
print('array1d > 5 불린 인덱싱 값 :', array3)

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

행렬의 정렬

np.sort()로 정렬

  • 넘파이에서 행렬을 정렬하는 대표적인 방법인 np.sort()는 원행렬은 그대로 유지한 채 원 행렬의 정렬된 행렬을 반환한다
org_array=np.array([3, 1, 9, 5])
print('원본 행렬:', org_array)

# np.sort()로 정렬

sort_array1 = np.sort(org_array)
print(sort_array1)

print('np sort로 호출 후 원본 행렬:', org_array)

원본 행렬: [3 1 9 5],
[1 3 5 9]
np sort로 호출 후 원본 행렬: [3 1 9 5]

ndarray.sort()로 정렬

  • ndarray.sort()는 원 행렬 자체를 정렬한 형태로 변환하며 반환값은 없다
sort_array2 = org_array.sort()
print('org_array.sort() 호출 후 반환된 행렬:', sort_array2)
print('원본 행렬: ', org_array)

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

내림차순 정렬

  • 내림차순 정렬은 [::-1]을 적용한다 np.sort()[::-1]과 같이 사용
# 내림차순 정렬
sort_array1_desc = np.sort(org_array)[::-1]
print(sort_array1_desc)

[9 5 3 1]

2차원 정렬

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

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

sort_array2d_axis0 = np.sort(array2d, axis=0)
print('로우방향정렬:\n', sort_array2d_axis0)
sort_array2d_axis1 = np.sort(array2d, axis=1)
print('컬럼방향정렬:\n', sort_array2d_axis1)

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

정렬된 행렬의 인덱스 반환 np.argsort()

  • 원본 행렬이 정렬되었을 때 기존 원본 행렬의 원소에 대한 인덱스를 필요로 할 때 np.argsort()를 이용한다
# 정렬된 행렬의 인덱스 반환하기

org_array = np.array([3, 1, 9, 5])
sort_indices = np.argsort(org_array)
print(type(sort_indices))
print(sort_indices)

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

=>argsort()로 학생성적을 정렬

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

sort_indices_asc = np.argsort(score_array)
print('성적 정렬시 점수 인덱스:', sort_indices_asc)
print('성적 오름차순 정렬 학생 이름 출력: ', name_array[sort_indices_asc])

성적 정렬시 점수 인덱스: [0 2 4 1 3]
성적 오름차순 정렬 학생 이름 출력: ['John' 'Sarah' 'Samuel' 'Mike' 'Kate']


행렬 내적(행렬 곱)

  • 행렬 내적은 np.dot()을 이용해 계산이 가능하다
# 행렬 내적(곱)

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(dot_product)

[[ 58 64],
[139 154]]

전치 행렬

  • 전치 행렬은 transpos()를 이용해 구한다
 # 전치 행렬

A = np.array([[1, 2], [3, 4]])
transpose_mat = np.transpose(A)

print('A의 전치행렬:\n', transpose_mat)

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


Reference 권철민, 파이썬 머신러닝 완벽 가이드, 위키북스2020

0개의 댓글