본문 바로가기
컴퓨터/파이썬

[Python] 넘파이(numpy) 라이브러리 간단 정리/넘파이 함수

by 도도새 도 2023. 1. 17.

넘파이 간단 정리

 

 

 

이전에 학교에서 파이썬을 한 학기 동안 다룬 적이 있었으나, 사실상 입문용으로 다룬 느낌이었다. 즉 학교에서 프로그래밍 입문 언어로 Python을 가르쳐 준 느낌. 그 이후에는 안드로이드 프로그래밍을 할 때 머신 러닝 적용에 실습 코드로 주어진 파이썬을 접한 게 다였다.

 

그러다 주식 데이터를 받아와 처리하여 원하는 정보를 얻을 필요가 생겼다. 또한 졸업 과제를 위해 각종 데이터 처리를 할 일이 생겼다. 이를 위해 적절한 json 데이터를 얻기 위해, 즉 데이터를 가공하기 위해 파이썬을 공부할 필요를 느꼈고, 그중에서도 넘파이와 판다스를 정리할 필요를 느꼈다.

 

주먹구구식으로 검색해가며 원하는 것을 수행해나가려했으나 이런 방식으로는 기본이 잡히지 않고, 코드 또한 무척 비효율적으로 작성됨을 느껴서 간단히 정리하는 바이다.

 

필자가 그나마 다뤄본 언어가 C, C++JS이기에 간혹 포스팅 내부에 스스로 이해하기 위한 비교가 들어갈 수 있다.

 

넘파이란?

 

넘파이는 파이썬 외부 라이브러리이다. 행렬계싼을 편하게 하기 위한 라이브러리이다.

 

ndarray

ndarray는 넘파이의 기본 배열 자료형이다. 파이썬은 기본적으로 list자료형을 가진다. 반면 ndarray는 c언어 등의 배열과 닮았다. 파이썬 list와 넘파이 ndarray의 차이는 아래와 같다.

 

  리스트 ndarray
배열 구조 무엇이든 산관 없음 요소 배열 크기가 모두 같아아함(정사각형 모양)
배열간 연산 연결만 지원 사칙연산 등 지원
인덱싱(접근) 하나의 요소만 접근 가능 여러 요소 동시 접근 가능
내부 자료형 다양한 자료형 혼재 가능 모두 같은 자료형만 가능

 

* 파이썬의 리스트와 C언어, C++등의 배열은 동적이나 아니냐의 차이가 있다. 또한 파이썬의 리스트는 C++ STD::list처럼 요소로 크기가 꽉 채워지면 공간을 늘리는 방식으로 동작한다. 일반적으로 리스트는 배열보다 느리다. (파이썬의 list는 이중 포인터 방식으로 구현이 되었기 떄문이라고 한다.)

 

ndarray 생성

넘파이 배열을 생성하기 위해서 사용 가능한 함수를 정리한다. 

 

np.array(object, dtype)

array함수는 기존 파이썬의 리스트, 튜플 등을 ndarray로 변경한다.

 

object : ndarray로 변환할 배열, 튜플 등

dypte : ndarray 내부 요소의 자료형(앞서 ndarray는 모든 요소가 하나의 자료형을 가진다고 한 바 있음) 생략 가능

*dypte은 생략할 경우 배열 내의 상위 자료형으로 통일시킨다.

 

 

import numpy as np

arr1 = np .array ([1 , 2 , 3 ])

arr2 = np .array ([1 , 2.0 , 3 ])

arr3 = np .array ([1 , 2.0 , "3"])

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

display(arr1 , arr2 , arr3 , arr4 )

print (arr1 .shape , arr4 .shape )

출력값

array([1, 2, 3])

array([1., 2., 3.])

array(['1', '2.0', '3'], dtype='

array([[1, 2, 3],

(3,) (2, 3)

* shape속성으로 배열의 모양을 확인 할 수 있다. 위의 결과에서 arr1은 크기가 3임을, arr4 2 3열임을 나타낸다.

 

arange(start, stop, step)

arange 파이썬의 range함수와 유사하게 사용한다. 시작점에서 끝 점까지 step만큼 증가시키며 narray를 만든다. 예를 들어 stop이 5면 0~4까지 생성된다.

start : (생략 가능) 기본값 0

step : (생략 가능) 기본값 1

 

 

import numpy as np

arr1 = np.arange(0 , 10 , 1 )

arr2 = np.arange(9 , -1 , -1 )

arr3 = np.arange(3 , 11 , 3 )

display(arr1, arr2, arr3)

출력값

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

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

array([3, 6, 9])

 

np.linspace(시작점, 끝점, 요소개수)

시작점과 끝점 사이에서 요소 개수에 맞게 자동 할당하여 narray를 생성한다.

 

np.zeros(shape, dtype)

shape의 형태에 맞게 0으로 채운 배열을 생성한다.

dtype: (생략 가능) 기본적으로 float자료형으로 생성

 

import numpy as np

arr1 = np .zeros ([3 , 5 ])

display(arr1 )

출력값

array([[0., 0., 0., 0., 0.],

[0., 0., 0., 0., 0.],

[0., 0., 0., 0., 0.]])

 

+ 배열 구조 변경

reshape함수를 사용하면 배열의 형태를 재조정 할 수 있다.

 

arr.reshape(shape)

shape 형태에 맞게 배열 형태를 재조정한다. 형태의 크기가 안 맞으면 오류가 발생한다.

 

import numpy as np

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

arr2 = np .zeros ([9 , ], int )

display(arr1 .reshape ((3 , 2 )), arr2 .reshape ((3 , 3 )))

출력값

array([[1, 2],

[3, 4],

[5, 6]])

array([[0, 0, 0],

[0, 0, 0],

[0, 0, 0]])

 

배열간 연산

 

넘파이의 배열은 각종 벡터 연산을 지원한다. 실제 사용도 그저 + - * /등의 형태로 사용하면 되어 간편하다. 심지어 속도 또한 반복문을 반복하여 각 요소에 접근하여 연산을 적용하는 것보다 훨씬 빠르다.

 

유니버셜 함수

 

유니버셜함수(ufunc)ndarray 안에 있는 데이터의 원소별로 연산을 수행해주는 함수이다. 다시 말해 행렬 간 연산을 쉽게 수행해주는 함수이다.

 

사용법은 기존 산술 연산자와 이름을 같이한다.

형태 쓰임
+ 덧셈
- 뺄셈
* 곱셈
% 나머지 연산
** 제곱

 

import numpy as np

arr1 = np .array ([[1 , 2 , 3 , 4 , 5 ], [6 , 7 , 8 , 9 , 10 ]])

arr2 = np .array ([[5 , 4 , 3 , 2 , 1 ], [10 , 9 , 8 , 7 , 6 ]])

arr3 = arr1 + arr2

display('배열 + 배열', arr1 + arr2 ) #배열 + 배열

display('배열 + 상수', arr1 + 3 )# 배열 + 상수

display('배열 - 배열', arr1 - arr2 )

display('배열 * 배열',arr1 * arr2 )# 배열 * 배열

display('배열 * 상수',arr1 * 3 ) #배열 * 상수

display('배열 / 배열', arr1 / arr2 )

display('배열 **2', arr1 **2 )

display('배열 % 상수', arr1 % 3 )

출력값

'배열 + 배열'

array([[ 6, 6, 6, 6, 6],

[16, 16, 16, 16, 16]])

'배열 + 상수'

array([[ 4, 5, 6, 7, 8],

[ 9, 10, 11, 12, 13]])

'배열 - 배열'

array([[-4, -2, 0, 2, 4],

[-4, -2, 0, 2, 4]])

'배열 * 배열'

array([[ 5, 8, 9, 8, 5],

[60, 63, 64, 63, 60]])

'배열 * 상수'

array([[ 3, 6, 9, 12, 15],

[18, 21, 24, 27, 30]])

'배열 / 배열'

array([[0.2 , 0.5 , 1. , 2. , 5. ],

[0.6 , 0.77777778, 1. , 1.28571429, 1.66666667]])

'배열 **2'

array([[ 1, 4, 9, 16, 25],

[ 36, 49, 64, 81, 100]], dtype=int32)

'배열 % 상수'

array([[1, 2, 0, 1, 2],

[0, 1, 2, 0, 1]], dtype=int32)

 

절댓값 연산

 

np.abs(array)

array의 절대값을 반환한다.

 

비교 연산

 

비교 연산자를 이용하여 배열의 요소에 대한 비교 연산을 할 수 있다. , 각자에 대응되는 요소끼리 비교 연산을 진행하여 truefalse 배열을 반환한다.

 

arr1 = np.array([[1 , 2 , 3 , 4 , 5 ], [6 , 7 , 8 , 9 , 10 ]])

arr2 = np.array([[5 , 4 , 3 , 2 , 1 ], [10 , 9 , 8 , 7 , 6 ]])

arr3 = arr1

print ('arr1 == arr2', arr1 == arr2)

print ('arr1 != arr2', arr1 != arr2)

print ('arr1 == arr3', arr1 == arr3)

print ('arr1 >arr2', arr1 >arr2)

 

출력값

arr1 == arr2 [[False False True False False]

[False False True False False]]

arr1 != arr2 [[ True True False True True]

[ True True False True True]]

arr1 == arr3 [[ True True True True True]

[ True True True True True]]

arr1 > arr2 [[False False False True True]

[False False False True True]]

이외에 지수로그, 삼각함수 등의 유니버셜 함수 역시 사용 가능하다.

 

배열 인덱싱

 

인덱스로 접근(인덱싱)

 

 ndarray의 인덱식와 슬리이싱은 기존 파이썬의 리스트와 같다. 배열 요소의 인덱스는 앞에서부터 0, 1, 2, 3...순이며, 뒤에서부터 1, -2, -3... 순서이다. (뒤 요소부터 1로 시작하는 인덱스로 접근 가능하다는 것이 낯설면서도 유용해 보인다.

 

 * 음수 인덱스로 뒤쪽 요소에 접근하는 것은 C언어, JS등의 배열은 지원하지 않는 기능이다. C언어의 경우 음수 인덱스를 실제로 메모리에 엑세스는 한다. 즉 메모리에 값만 할당 된다면 정상적으로 해당 값을 읽겠지만, 굳이 쓸 이유는 없어보인다.

(+ 자바 스크립트의 배열은 엄밀히 말해 배열이 아니라 해쉬 맵이다. c++ std::list[]를 이용한 인덱스로 접근 자체가 불가능하다.)

 

 파이썬 리스트에서는 2차원 리스트에서 특정 값을 list[i][j]로 가져온다. 그러나 ndarray에서는 튜플로 특정 값을 가져오는 것이 권장된다. 즉 아래와 같은 형태를 사용한다.

 

array[i, j]

 

li = [[1 , 2 , 3 ], [4 , 5 , 6 ]]

print (li [0 ][1 ])

arr = np .array (li )

print (arr [0 , 0 ], arr [0 ][0 ])

결과값

2

1 1

 

불리언 인덱스

 

배열과 형태가 맞는 부울 리스트를 인덱스로 사용 할 수 있다. 이를 불리언 인덱스라고 부른다.

 

import numpy as np

arr = np .arange (5 )

inx = [True , False , True , False , True ]

display(arr [inx ])

결과값

array([0, 2, 4])// True에 해당하는 값만 추출됨을 볼 수 있다.

 

연산자를 활용한 불리언 인덱스

 

비교 연산자로 조건을 주어 불리언 인덱스를 활용 할 수 있다.

 

import numpy as np

arr = np .arange (5)

a1 = (arr >= 3) # 3이상 값만을 True로 하는 불리언 배열 생성

display(a1)

display(arr [a1])#3이상 값만을 추출

결과값

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

array([3, 4])

 

각종 집계 함수

 

넘파이는 각종 집계 함수를 지원한다. 집계함수는 대체로 아래와 같은 형태로 이용 가능하다.

 

np.sum(arr, axis)

arr의 전체 값의 합을 구한다.

arr : 합을 구할 배열

axis : 축값, 값을 주지 않으면 모든 원소의 합계가 아닌 특정 축을 기준으로 합을 구한다.

axis = 0 : 행 방향(위에서 아래 방향)으로 합을 구한다. 즉 결과값은 각 행의 합을 요소라 하는 배열

axis = 1 : 열 방향(왼쪽에서 오른쪽 방향)으로 합을 구한다. 즉 결과값은 각 열의 합을 요소로 하는 배열

 

import numpy as np

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

display(arr )

display(np .sum (arr ))

display(np .sum (arr , axis =0 ))

display(np .sum (arr , axis =1 ))

결과값

array([[1, 2, 3],

[4, 5, 6]])

21

array([5, 7, 9])

array([ 6, 15])

 

이하 집계 함수가 작동하는 방식도 이와 동일하다.

sum 합을 구함
min 최소값을 구함
max 최대값을 구함
mean 평균을 구함
std 표준편차를 구함
median 중위수를 구함
unique 중복되지 않은 유일한 값을 구함

 

import numpy as np

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

display(np .sum (arr , axis =0 )) # 합계

display(np .max (arr , axis =0 )) # 최대값

display(np .min (arr , axis =0 )) # 최소값

display(np .mean (arr , axis =0 )) # 평균

display(np .median (arr , axis =0 )) # 중위수

display(np .unique (arr , axis =0 )) # 유일한값

결과값

array([5, 7, 9])

array([4, 5, 6])

array([1, 2, 3])

array([2.5, 3.5, 4.5])

array([2.5, 3.5, 4.5])

array([[1, 2, 3],

[4, 5, 6]])

 

추후 사용하게 될 집계함수를 검색해가며 사용하는 방법이 제일 적절할 것이다.

'컴퓨터 > 파이썬' 카테고리의 다른 글

[Tensorflow] 텐서플로우 버전 확인하기  (0) 2023.02.14

댓글