넘파이(Numpy)는 파이썬 표준라이브러리를 확장하는 모듈이며, 수치 데이터(numerical data)를 용이하게 생성 및 조작하기 위해 유용하게 사용된다.
이번 장에서는 넘파이 모듈의 기본 사용법을 소개한다.
넘파이 관련 내용은 아래 사이트에서 제동하는 자료를 참고한다.
파이썬에서 기본적으로 사용할 수 있는 수 관련 객체에는 크게 두 종류가 있다.
하지만 이전에 살펴보았듯이 튜플의 경우는 수정이 안되는 등 유연성이 떠어지고, 리스트의 경우는 길이가 몇 만, 몇 십만, 몇 백만 처럼 매우 길어지면 데이터를 조작하는 데에 많은 시간이 소요되는 단점이 있고, 사전의 경우는 조작 속도는 매우 빠르나 키와 키값을 항상 사용해야 해서 문법상 제약이 따른다. 또한 행렬 등 다차원 시퀀스 데이터는 처리하기 힘들다.
넘파이(numpy) 모듈은 언급한 단점을 극복하기 위해 만들어진 라이브러리이며, 다음의 특징을 갖고 있다.
넘파이 모듈을 사용하려면 먼저 numpy 모듈을 추가 설치해야 한다. 하지만 Anaconda 등을 사용하면 이미 설치되어 있고 넘파이 모듈을 임포트하기만 하면 된다. numpy 모듈의 약칭으로 np를 관례적으로 사용한다.
In [1]:
import numpy as np
넘파이 모듈에서 가장 주요한 요소는 어레이(array)이다.
어레이의 사용법은 리스트의 경우와 기본적으로 비슷하다.
먼저 0, 1, 2, 3
으로 구성된 어레이를 생성하고자 하면 array
함수를
사용하면 된다.
In [2]:
a = np.array([0, 1, 2, 3])
array
함수는 리스트, 튜플을 입력받아 어레이 객체를 되돌려준다.
리스트와 튜플 어느 것을 써도 리턴값은 동일하다.
위 정의를 튜플을 이용하여 정의해도 결과는 같다.
In [3]:
b = np.array((0, 1, 2, 3))
In [4]:
c = a == b
c
Out[4]:
주의: 어레이 객체들 사이의 비교는 각 항목별로 실행된다.
a == b
의 실행결과는 새로운 어레이이며 각 항목별로 비교한 결과인 불(bool) 값을
갖게 된다.
c
의 실행결과를 보면 dtype
이라는 키워드 인자가 추가되어 있다.
dtype
키워드는 생성된 어레이 객체의 각 항목의 자료형을 갖고 있다.
주의: 어레이 객체의 각 항목들은 모두 동일한 자료형이어야 한다.
리스트, 튜플과는 달리 어레이의 각 항목은 동일한 자료형들로 구성되어 있다.
변수 a
에는 int형 숫자들이 들어있다.
In [5]:
a.dtype
Out[5]:
변수 b
도 int형 숫자들로 구성되어 있다.
In [6]:
b.dtype
Out[6]:
반면에 변수 c
는 불값(bool)으로 구성되어 있다.
In [7]:
c.dtype
Out[7]:
a
또는 b
와는 달리 c
의 경우 dtype
명시하는 이유는
True, False
의 의미가 참, 거짓의 의미 외에 0
이 아닌 숫자, 0
인 숫자 또한
의미할 수 있기 때문이다.
다음의 경우 dtype
키워드 인자값으로 int
를 입력하면 자려형이 달리지는 것을
확인할 수 있다.
In [8]:
d = np.array([ True, True, True, True], dtype=int)
d.dtype
Out[8]:
In [9]:
d
Out[9]:
array
함수는 dtype
키워드 인자외에 copy
, order
, subok
, ndmin
등의
추가 키워드 인자를 사용할 수 있다.
각 키워드 인자의 활용은 필요할 경우 추가로 설명되어질 것이다.
In [10]:
L = range(1000)
%timeit
은 ipython에서 간단한 코드의 실행시간을 테스트하는 기능을 갖는다.
아래 코드는 0부터 999까지의 숫자를 각각 제곱하여 새로운 리스트를 생성하는 리스트 조건제시법 코드이다.
In [11]:
%timeit [i**2 for i in L]
arange
함수는 range
와 동일한 기능을 수행한다.
다만 리스트가 아닌 어레이를 리턴한다.
In [12]:
a = np.arange(1000)
앞서 두 개의 리스트를 비교할 때 처럼 어레이 관련 연산은 기본적으로
각 항목별로 실행된다.
따라사 a ** 2
는 각 항목을 제곱하라는 함수를 실행한다.
In [13]:
%timeit a**2
In [14]:
np.array?
특정 성질과 관련된 함수들을 찾고자 할 경우 lookfor
함수를 사용한다.
예를 들어 어레이를 생성하는 기능과 관련된 함수를 찾고자 할 경우 다음과 같이
실행하면 된다.
np.lookfor('create array')
그러면 numpy 모듈 안에 정의된 모든 함수들의 주석(docstring)에
create
와 array
가 함께 포함되어 있는 함수들의 리스트를 보여준다.
In [15]:
np.lookfor('create array')
*
)와 물음표(?
)를 응용하면 관련 함수들을 찾아준다.
예를 들어 con
으로 시작하는 넘파이 함수를 찾고자 하면 다음과 같이 실행하면 된다.
In [16]:
np.con*?
In [17]:
a = np.array([0, 1, 2, 3])
a
Out[17]:
a
에는 1차원 어레이가 할당되었다.
In [18]:
a.ndim
Out[18]:
생성된 어레의 _모양(shape)_은 shape
인스턴스변수를 이용하여 확인한다.
In [19]:
a.shape
Out[19]:
즉, 변수 a
에 할당된 어레이 array([0, 1, 2, 3])
는
위 행렬을 1차원 어레이를 표현한다면 아래와 같은 모양이다.
$$\left [ \begin{matrix} 0 \\ 1 \\ 2 \\ 3 \end{matrix} \right ]$$즉, 길이가 d
인 1차원 어레이는 d x 1
행렬에 대응한다.
주의: ndim
, shape
는 어레이 클래스에서 선언된 인스턴스변수이다.
클래스에는 기본적으로 변수와 함수가 포함되는데 클래스에서 선언된 변수를 인스턴스변수, 멤버변수, 또는 _속성_이라 부르고, 함수를 _메소드_라 부른다.
어레이 객체와 함께 사용할 수 있는 다른 인스턴스변수와 메소드는 이후에도 필요할 때마다 설명될 예정이다.
In [20]:
b = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
b
Out[20]:
즉, 앞서 언급된 행렬의 첫째 행이 위 어레이의 첫 번째 리스트로, 그리고 둘째 행이 어레이의 두 번째 리스트에 해당한다.
어레이의 차원은 ndim
인스턴스변수를 이용하여 확인한다.
In [21]:
b.ndim
Out[21]:
변수 b
에 할당된 어레이의 모양(shape)은 2 x 3
행령에 해당하는 (2, 3)
이다.
In [22]:
b.shape
Out[22]:
len
함수는 첫번째 차원의 길이를 되돌려 준다.
In [23]:
len(b)
Out[23]:
In [24]:
a = np.arange(10) # range(10)과 동일
a
Out[24]:
In [25]:
b = np.arange(1, 9, 2) # range(1, 9, 2)와 동일
b
Out[25]:
In [26]:
c = np.linspace(0, 1, 6) # 구간의 시작, 구간의 끝, 점의 개수
c
Out[26]:
In [27]:
d = np.linspace(0, 1, 6, endpoint=False)
d
Out[27]:
In [28]:
e = np.ones((3, 3)) # 인자: 원하는 모양(shape)의 튜플값
e
Out[28]:
In [29]:
e = np.zeros((2, 2)) # 인자: 원하는 모양(shape)의 튜플값
e
Out[29]:
In [30]:
e = np.eye(3) # 인자:원하는 모양(shape)의 어레이의 길이(len)
e
Out[30]:
In [31]:
e1 = np.diag((1, 2, 3, 4)) # 인자: 튜플, 리스트 또는 1차원 어레이
e1
Out[31]:
In [32]:
e2 = np.diag([1, 2, 3, 4]) # 인자: 튜플, 리스트 또는 1차원 어레이
e2
Out[32]:
In [33]:
e3 = np.diag(np.arange(1,5)) # 인자: 튜플, 리스트 또는 1차원 어레이
e3
Out[33]:
In [34]:
e1 == e2
Out[34]:
In [35]:
e2 == e3
Out[35]:
난수(random number)들로 이루어진 어레이를 구할 수 있다.
numpy.random
모듈에 있는 rand
, randn
함수를 활용할 수 있다.
numpy.random.rand
함수: 0과 1사이에서 난수를 구한다. 방식은 균등분포를
사용한다.numpy.random.randn
함수: 가우시안(Gaussian) 정규분포 방식을 사용하여
난수를 구한다. 각 함수의 인자는 원하는 모양(shape)에 해당하는 튜플이다.
단, numpy.ones
또는 numpy.zeros
함수들과는 달리 괄호를 사용하지 않는다.
In [36]:
f = np.random.rand(4)
f
Out[36]:
In [37]:
f1 = np.random.rand(2, 3)
f1
Out[37]:
In [38]:
g = np.random.randn(4)
g
Out[38]:
In [39]:
g1 = np.random.randn(1, 2)
g1
Out[39]:
주의
난수 관련 함수들이 생성하는 난수는 사실 정말로 무작위로
생성되지는 않는다.
각 프로그래밍 언어마다 난수를 만드는 방식이 정해져 있고,
정해진 방식에 맞추어 이미 난수표를 갖고 있다.
즉, rand
함수가 호출되는 순서에 따라 사실 동일한 숫자를
생성하지만 사람 눈에는 무작위 숫자들로 보이는 것 뿐이다.
이런 현상을 해결하기 위해 시드(seed) 값을 사용하여 생성되는 난수의 순서를 보다 무작위적으로 보여지게 할 수 있다. 예를 들어 시드값을 0을로 하면 매번 동일한 난수들이 생성되는 것을 아래와 같이 확인할 수 있다.
In [40]:
np.random.seed(0) ; np.random.rand(4)
Out[40]:
In [41]:
np.random.seed(0) ; np.random.rand(4)
Out[41]:
시드값을 변경하면 생성되는 난수들을 정말로 무작위처럼 보이게 할 수 있다.
In [42]:
np.random.seed(1234) ; np.random.rand(4)
Out[42]:
In [43]:
np.random.seed(2000) ; np.random.rand(4)
Out[43]:
In [44]:
a = np.array([1, 2, 3])
a.dtype
Out[44]:
위 어레이의 dtype
을 float
로 바꾸고자 한다면 dtype 키워드 인자를 사용해야 한다.
In [45]:
b = np.array([1, 2, 3], dtype=float)
b.dtype
Out[45]:
새로 생성된 어레이의 모양도 다르다.
In [46]:
b
Out[46]:
물론 애초부터 float 자료형으로 선언할 수 있다.
In [47]:
a = np.array([1., 2, 3.])
a.dtype
Out[47]:
어레이가 기본적으로 사용하는 자료형은 float
이다.
In [48]:
a = np.ones((3,3))
a.dtype
Out[48]:
np.ones
함수의 기본 정의를 확인하면 보다 정확히 알 수 있다.
In [49]:
np.ones?
int
와 float
이외에도 다음의 자료형들이 어레이에서 지원된다.
complex: 복소수 자료형
In [58]: d = np.array([1+2j, 3+4j, 5+6j]).dtype
Out[58]: dtype('complex128')
bool: 불리언 자료형
In [59]: e = np.array([True, False, False, True]).dtype
Out[59]: dtype(’bool’)
S: 문자열 자료형
In [60]: f = np.array([’Bonjour’, ’Hello’]).dtype
Out[60]: dtype(’S7’)
등등.
주의:
int32, int64, float64, S8, S12
자료형 이름 뒤에 숫자가 사용되기도 한다.
이는 어레이에서 사용되는 각각의 항목의 값들이 가질 수 있는 최대 크기를 의미한다.
즉, 사용된 정수들이 32비트로 모두 담을 수 있는지, 또는 사용된 문자열들의 길이가 최대 8바이트 또는 12바이트 인지를 나타낸다.
예를 들어 아래 문자열로 이루어진 어레이에서 가장 긴 문자열이 4바이트이기 때문에,
dtype이 'S4'
이다.
In [50]:
np.array(['ab', 'abc', 'abcd']).dtype
Out[50]: