본문 바로가기
Data Science/파이썬으로 데이터분석 하기

파이썬으로 데이터 분석하자 (3) - NumPy 기본

by 싸코 2017. 10. 9.

파이썬 Numpy  - 파이썬 라이브러리를 활용한 데이터 분석 中

※본 포스팅은 "파이썬 라이브러리를 활용한 데이터 분석"을 기억이 나지 않을 때 다시 돌아볼 목적으로 필요 내용만 간단하게 정리하였습니다.


2017/09/19 - [Data Science/Python] - 파이썬으로 데이터 분석하자 (1)

2017/09/27 - [Data Science/Python] - 파이썬으로 데이터 분석하자 (2) - IPython 사용하기



NumPy 기본


Numpy는 고성능 과학계산을 위한 데이터분석 패키지이다. 주요 기능은 다음과 같음.

  • 벡터 산술연산
  • 다차원배열 ndarray
  • 표준 수학 함수
  • 선형대수, 난수 생성, 푸리에 변환


1. ndarray

1.1 배열 생성함수

1.2 배열의 데이터 타입

1.3 배열과 스칼라 연산

1.4 NumPy 배열 색인과 슬라이싱

1.5 불리언 색인


2. 유니버설 함수 ufunc


3. 배열을 사용한 데이터 처리

3.1 조건절 표현

3.2 통계 메서드

3.3 불리언 메서드

3.4 정렬 메서드

3.5 집합 함수


4. 배열의 파일 입출력


5. 선형대수


6. 난수 생성


1. ndarray 다차원 배열 객체

ndarray는 같은 종류의 데이터를 담을 수 있는 포괄적인 다차원 배열이다. ndarray의 모든 원소는 같은 자료형이어야만 한다.
 - shape : 모든 배열은 각 차원의 크기를 알려주는 튜플. 차원의 구조를 볼때 사용 (행,렬)로 표시됨
 - dtype : 배열에 저장된 자료를 알려주는 객체


1.1 배열 생성 함수

np.array()

순서가 있는 객체(주로 리스트)를  넘겨받아 데이터가 들어있는 새로운 NumPy 배열 생성

다차원 배열 생성시 배열의 길이가 동일해야 함.
다차원 배열은 일종의 매트릭스와도 비슷하다.

순서가 있는 배열은 벡터(;크기와 방향을 가진 양; 수와 순서쌍으로 구성)와도 비슷해보임

 - np.array.ndim : 차원 수 (행)


np.zeros , np.ones

 - 각각 0과 1이 들어있는 배열을 생성한다.

 - 다차원 배열을 생성하려면 (행,열)로된 튜플을 넘기면 된다.

>> np.zeros(3,4)

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

           [0,0,0,0],

           [0,0,0,0])


np.empty

 - 초기화가 없는 값으로 배열을 반환함


np.arange(n)

배열 버전의 range 함수, 자료형을 명시하지 않으면 float64임.


<배열 생성 함수 리스트>

함수

내용 

np.array

입력된 데이터를 ndarray로 변환. dtype을 명시하면 자료형을 설정할 수 있다

np.asarray

입력 데이터를 ndarray로 변환하나 이미 ndarray일 경우에는 새로 메모리에 ndarray가 생성되지는 않는다

np.arange 

range 함수와 유사하나 ndarray를 반환 

np.ones 

전달인자로 전달한 dtype과 모양(행,렬)으로 배열을 생성하고 모든 내용을 1로 초기화하여 ndarray를 반환

np.zeros 

ones와 같으나 초기값이 0이다 

np.empty 

ones와 zeros와 비슷하나 값을 초기화하지는 않는다




1.2 배열의 데이터 타입


np.array(list, dtype=np.float64)
이런 식으로 처음에 데이터 타입을 명시할 수 있다.

array.dtype
을 하면 해당 ndarray의 데이터 타입을 확인할 수 있다.

NumPy의 자료형을 모두 외울 필요는 없지만 어떤 것들이 있는지 알고 검색해서 따다 사용할 수는 있어야 한다.
주로 사용하는 dtype은 부동소수점(float), 복소수(complex), 정수(int), 불리언(bool), 문자열(string_), 파이썬 객체(object) 이다.



1.3 배열과 스칼라 연산

다른 포스팅에서도 언급했지만 NumPy의 큰 장점은 벡터 연산이 가능하다는 것이다.
for문을 사용하지 않고도 우리가 원하는 배열 연산을 NumPy를 활용하면 직관적으로 이를 수행할 수 있다.

배열은 우리가 아는 리스트 형태라고 생각하면 되고, 스칼라는 단일 값이라고 생각하면 편하다
(1, 2, 3) 라는 벡터에 2라는 스칼라를 곱하면 (2, 4, 6)이라는 결과를 얻을 수 있다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
arr = np.array([[1,2,3], [4,5,6]])
 
In [4]: arr
Out[4]:
array([[123],
       [456]])
 
In [5]: arr*arr
Out[5]:
array([[ 1,  4,  9],
       [162536]])
 
In [6]: arr-arr
Out[6]:
array([[000],
       [000]])
cs



크기가 다른 배열 간의 연산은 브로드캐스팅(Broadcasting)이라고 한다. 이 개념은 딥러닝의 기본적인 개념을 이해할 때 꼭 나오는 개념이므로 반드시 숙지할 수 있도록 한다.


2017/10/09 - [Data Science/Python] - Python 기초 - NumPy Broadcasting 이해하기 (2)





1.4 NumPy 배열 색인과 슬라이싱

1.4.1 NumPy 배열과 Python 리스트 비교 차이

파이썬 리스트와 유사하게 색인과 슬라이싱이 동작한다.

In [9]: arr = np.arange(10)

In [10]: arr
Out[10]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

In [11]: arr[5]
Out[11]: 5

In [12]: arr[5:8]
Out[12]: array([5, 6, 7])


하지만 파이썬 리스트와 큰 차이점은 NumPy 배열 연산에서 다루었듯이 NumPy 배열에서는 브로드캐스팅 개념이 적용되어 for문을 사용하지 않고도 계산했고 슬라이싱에서도 마찬가지로 for문을 사용하지 않고 바로 슬라이싱에 값을 입력할 수 있다. 아래 예제코드를 살펴보자.



In [13]: arr[5:8] = 100

In [14]: arr
Out[14]: array([  0,   1,   2,   3,   4, 100, 100, 100,   8,   9])

In [17]: li = list(range(10))


In [18]: li

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


In [19]: li[5:8]

Out[19]: [5, 6, 7]


In [20]: li[5:8] = 100

---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-20-6343c1835cd7> in <module>()

----> 1 li[5:8] = 100


TypeError: can only assign an iterable


NumPy 배열은 슬라이싱에 100이라는 값이 한 번에 다중할당 됐지만, 파이썬 리스트의 경우에는 불가능했다. for문을 이용해서 각 색인(index)별로 꺼내서 할당해야 한다.


또 한가지 큰 차이점은 NumPy 배열이 새로운 값을 슬라이싱에 할당했을 때, 할당하면서 할당된 배열이 새롭게 생성되어 반환되는 것이 아니라 기존 배열의 값을 수정한다는 사실이다. 데이터 값이 복사되어 새롭게 배열이 생성되는 것이 아닌 것이다. 이는 NumPy가 대용량 데이터 처리를 염두에 두고 성능을 위해서 이와 같이 동작한다. arr[5:8].copy()를 사용하면 새로 배열이 생성되어 반환될 것이다.



1.4.2. 다차원 배열의 색인

다차원 배열의 색인은 차원을 콤마로 구분해서 넘기면 쉽게 색인이 가능하다

array[a, b]

In [24]: arr2d = np.array([[1,2,3],[4,5,6],[7,8,9]])


In [25]: arr2d

Out[25]:

array([[1, 2, 3],

       [4, 5, 6],

       [7, 8, 9]])


In [26]: arr2d[0][2]

Out[26]: 3


In [27]: arr2d[0,2]

Out[27]: 3



다차원 배열 색인의 또 다른 특징은 축을 기준으로 슬라이싱이 가능하다는 점이다.


arr[a:b, c:d]


위와 같은 방식으로 축 별로 슬라이싱이 가능하다는 것이 특징이다


In [29]: arr2d[:2, 1:]

Out[29]:

array([[2, 3],

       [5, 6]])


0번 축으로는 첫 번째, 두 번째 배열이,

1번 축으로는 두 번째, 세 번째 값이 슬라이싱되었다.


0번 축과 1번 축이라는 말이 이해하기 어렵다면, 0번을 행으로 1번을 열이라고 생각하면 2차원 배열의 슬라이싱 색인은 감이 올 것이다.


콜론(:)만 쓰면 전체 축을 선택한다는 의미이다.


값을 할당하는 것도 위에서 다룬 것과 동일하게 슬라이싱 된 영역에 값이 할당된다.



1.5 불리언 색인

실제 데이터 분석에서 전처리를 하거나 통계 정보를 수집할 때 불리언 색인을 많이 사용한다.


흥미로운 점은 앞서 다루었던 배열의 산술연산과 마찬가지로 비교연산(불리언 연산; ==, !=)도 동일하게 된다는 것이다.


In [30]: names = np.array(['철수', '영희', '말자', '숙자'])


In [31]: names

Out[31]:

array(['철수', '영희', '말자', '숙자'],

      dtype='<U2')


In [32]: names == "철수"

Out[32]: array([ True, False, False, False], dtype=bool)


In [33]: data = np.random.randn(4,4)


In [34]: data

Out[34]:

array([[ 0.77506965,  0.17587039,  0.18663466,  0.02516594],

       [ 0.01509111, -1.59789039,  0.33673635,  0.2034544 ],

       [-0.40241337, -1.55254101, -0.44145021, -1.14091301],

       [-1.80956336,  1.0140776 ,  1.26199964,  1.32135321]])


In [35]: data[names=="철수"]

Out[35]: array([[ 0.77506965,  0.17587039,  0.18663466,  0.02516594]])


비교연산으로 True만 출력할 수 있도록 다음과 같이 할 수 있다. 비교연산을 위해 논리연산을 사용하기 위해서는 파이썬 예약어 and, or는 사용할 수 없으므로 and는 &으로 or은 | 를 사용해야 한다.


값을 다중할당하는 것도 불리언색인을 위해서 할 수 있으며 다양한 데이터 전처리 상황에서 응용할 수 있다. 예를 들어 데이터 수집과정이나 전처리 목적에 따라 0 이하인 값을 0으로 치환해야 될 경우 한 줄로 이 모든 작업을 할 수 있다.


In [36]: data[data < 0] = 0


In [37]: data

Out[37]:

array([[ 0.77506965,  0.17587039,  0.18663466,  0.02516594],

       [ 0.01509111,  0.        ,  0.33673635,  0.2034544 ],

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

       [ 0.        ,  1.0140776 ,  1.26199964,  1.32135321]])





2. 유니버설 함수

unfunc라고 불리는 유니버설 함수는 ndarray 안에 있는 데이터 원소 별로 연산을 수행하는 함수다. 일종의 래퍼 함수로 래퍼 함수(wrapper function)는 간단하게 다른 함수에 약간의 기능을 덧씌워 사용하는 함수이다. 여기에서는 ndarray를 감싸 특정 연산을 고속으로 수행해주는 함수라고 보면 될 듯하다.

>> np.sqrt(np.arange(10))
>> np.exp(np.arange(10))

같이 add, maximum 등 다양한 유니버설 함수가 있다. 자주 사용하는 기능을 위한 NumPy 내장 함수(built-in)라고 생각하면 될 듯하다.


<NumPy Universal Function List>
단일 배열에 사용하는 함수

 함수

설명 

 abs, fabs

각 원소의 절대값을 구한다. 복소수가 아닌 경우에는 fabs로 빠르게 연산가능 

sqrt  

제곱근을 계산 arr ** 0.5와 동일 

square 

제곱을 계산 arr ** 2와 동일 

Exp 

각 원소에 지수 ex를 계산 

Log, log10, log2, logp 

각각 자연로그, 로그10, 로그2, 로그(1+x) 

sign 

각 원소의 부호를 계산 

ceil 

각 원소의 소수자리 올림 

floor 

각 원소의 소수자리 버림 

rint 

각 원소의 소수자리 반올림. dtype 유지 

modf 

원소의 몫과 나머지를 각각 배열로 반환 

isnan 

각 원소가 숫자인지 아닌지 NaN 나타내는 불리언 배열 

isfinite, isinf 

배열의 각 원소가 유한한지 무한한지 나타내는 불리언 배열 

cos, cosh, sin, sinh, tan, tanh

일반 삼각함수와 쌍곡삼각 함수 

logical_not 

각 원소의 논리 부정(not) 값 계산. -arr와 동일 



서로 다른 배열 간에 사용하는 함수

 함수

설명

 add

두 배열에서 같은 위치의 원소끼리 덧셈 

subtract 

첫번째 배열 원소 - 두번째 배열 원소

multiply 

배열의 원소끼리 곱셈 

divide

첫번째 배열의 원소에서 두번째 배열의 원소를 나눗셈 

power 

첫번째 배열의 원소에 두번째 배열의 원소만큼 제곱

maximum, fmax

두 원소 중 큰 값을 반환. fmax는 NaN 무시 

minimum, fmin

두 원소 중 작은 값 반환. fmin는 NaN 무시 

mod 

첫번째 배열의 원소에 두번째 배열의 원소를 나눈 나머지 

greater, greater_equal, less, less_equal, equal, not_equal 

두 원소 간의 >, >=, <, <=, ==, != 비교연산 결과를 불리언 배열로 반환 

logical_and, logical_or, logical_xor 

각각 두 원소 간의 논리연산, &, |, ^ 결과를 반환 






3. 배열을 사용한 데이터 처리

3.1 조건절 표현

np.where(조건, x, y)

조건이 참이면 x의 원소를, 거짓이면 y의 원소로 하는 벡터를 반환.
'x if condition else y'를 벡터화시킨 것.

In [38]: xarr = np.array([1,1,1,1,1])


In [39]: yarr = np.array([0,0,0,0,0])


In [40]: cond = np.array([True, False, True, True, False])


In [41]: result = np.where(cond, xarr, yarr)


In [42]: result

Out[42]: array([1, 0, 1, 1, 0])



3.2 통계 메서드

앞서 NumPy를 이용해서 기본적인 통계를 할 수 있다고 했다. NumPy에 내장 함수를 이용해서 총합, 평균과 같은 수학 계산을 할 수 있다.


<기본 NumPy 통계 메서드 리스트>

함수

설명 

sum

배열 전체 혹은 특정 축에 대한 모든 원소의 합을 계산 

mean

산술평균 

std, var 

표준편차와 분산, 자유도를 줄 수 있음 

min, max 

최소값, 최대값 

argmin, argmax 

최소원소의 색인 값, 최대원소의 색인 값 

cumsum 

각 원소의 누적 합 

cumprod 

각 원소의 누적 곱 



3.3 불리언 배열 메서드

불리언 배열에 대한 sum메서드를 실행해서 True인 원소의 개수 반환

any 메서드는 True인 값이 하나라도 있으면 True를,
all 메서드는 모든 값이 True일 때 True를 반환



3.4 정렬 메서드

파이썬 내장 리스트처럼 NumPy 배열도 sort메서드로 정렬 가능
전달인자로 축(axis)의 값을 전달해서 축별로 정렬도 가능



3.5 집합 함수

unique(x)
배열 x에서 중복된 원소를 제거한 후 정렬(sorted)하여 반환

intersect1d(x, y)
배열 x와 y에 공통적으로 존재하는 원소를 정렬(sorted)하여 반환

union1d(x, y)
두 배열의 합집합을 반환

in1d(x, y)
x의 원소 중 y의 원소를 포함하는지를 나타내는 불리언 배열을 반환

setdiff1d(x, y)
x와 y의 차집합을 반환

setxor1d(x, y)
한 배열에는 포함되지만 두 배열 모두에는 포함되지 않는 원소들의 집합인 대칭 차집합을 반환





4. 배열의 파일 입출력

np.save(파일명, ndarray)

np.load('파일명.npy')

np.savetxt, np.loadtxt




5. 선형대수

np.dot(x, y)
np.diag
np.trace
np.linalg.det
np.linalg.eig
np.linalg.inv
np.linalg.svd
np.linalg.solve
np.linalg.lstsq




6. 난수 생성

numpy.random 모듈의 함수

seed
난수 발생기 시드 지정

permutation
순서를 임의로 바꾸거는 임의의 순열 반환

shuffle
배열의 순서 섞기

rand
균등분포에서 표본 추출

randint
주어진 최소/최대 범위 안에서 임의의 난수 추출

randn
표준편차가 1이고 평균값이 0인 정규분포에서 표본 추출

binomial
이항부포에서 표본 추출

normal
정규분포에서 표본 추출

beta
베타분포에서 표본 추출

chisquare
카이제곱분포에서 표본 추출

gamma
감마분포에서 표본 추출

uniform
균등분포에서 표본 추출




댓글