목차


Part 2에서는 본격적으로 numpy와 pandas 등 데이터 분석 모델에 직접 넣을 데이터 셋을 다룰 것입니다.



numpy

numpy는 다차원 배열 생성 및 연산을 위한 패키지(모듈)로 딥러닝에 많이 쓰이는 자료 구조인 배열(array)가 내장되어 있습니다.

import numpy as np



배열 (array)

  • 다차원 구조

  • 동일한 데이터 타입만 허용

  • 딥러닝(neural + lots of hidden layers)에 많이 쓰이는 구조

1. 생성

입력 출력 값
a1 = np.arange(1,10)
a2 = np.arange(1,19, dtype = ‘float’)
a3 = np.array([1, 2, 3, 4])
a4 = np.array([[1,2],[3,4]])
arr1 = np.random.randn(5,4) 랜덤으로(random) 표준 정규분포(N(0,1))를 따르는 난수 생성 (5x4 size)

2. 주요 메소드 (암기!!)

메소드 설명 출력 값
a1.dtype a1를 구성하는 데이터 타입 dtype(‘int32’)
a1.shape a1의 사이즈(행 x 열) (9,)
a1.reshape(3,3) a1의 사이즈 변경
a2.reshape(2,3,3) a2의 [층, 행, 열] 변경
a2.reshape(2,3,3).ndim 차원의 갯수를 알려줌 3

3. 연산

a5 = np.array([10,20,30,40]).reshape(2,2)

a6 = np.array([10,20])

​연산 설명 출력
a4 + 1 스칼라 연산
a4 + a5 서로 같은 크기를 갖는 배열끼리 연산 가능
a4 + a6 서로 다른 크기를 갖는 배열과 연산 가능


Broadcast

: 배열에서는 반복연산으로 연산하고자 하는 두 배열의 크기가 다르더라도 연산이 되게 하는데 이를 Broadcast라고 합니다. 함수를 따로 사용하는 것은 아니고 아래 조건을 충족시키면 연산이 실행됩니다.

Broadcast가 실행되기 위해 두 배열이 만족해야할 조건

  1. 양쪽 배열에 크기를 나타내는 숫자가 동일해야합니다.

  2. 작은 쪽 배열의 크기를 나타내는 나머지 숫자는 반드시 1.

  3. 같은 크기의 숫자들은, 같은 방향에 있어야함

    (x, ..) + (x, 1)

[ 예제 1]

입력 형태
arr1 = np.arange(1,9).reshape(2,4)
arr2 = np.array([10,20])
arr3 = np.array([10,20,30,40]


연산 결과 형태
arr1 + arr2 연산 불가 (2x4) + (1x2)
arr1 + arr2.reshape(2,1) (2x4) + (2x1)
arr1 + arr3 (2x4) + (1x4)

4. 색인

배열의 색인은 리스트에서의 색인과 달리 여러 컬럼을 리스트 형태로 전달 가능합니다.(벡터 색인) 라벨 인덱싱(label indexing)은 불가능하며 위치로만 색인이 가능합니다.

아래 리스트 및 배열을 이용하여 예시를 살펴봅시다.

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

arr1 = np.array(L1)


입력 결과
L1[1,1] 1차원이기 때문에 불가
L1[1][1] 5
arr1[1,1] 5
arr1[0,] [1,2,3]
열 표시는 생략 가능
arr1[0,:] [1,2,3]
arr1[,0] 행 표시는 생략 불가
arr1[:,0] [1,4,7]
arr1[[0,2],:]
(벡터 색인)
arr1[1:3,:]
슬라이스 색인 가능


여러 예시들을 보았으니 반대로 배열 구조를 보고 어떻게 입력해야 나올지 고민해봅시다. 슬라이싱, 벡터 색인 등 다양한 방법이 있으니 여러가지 답안을 머릿속으로 그려보시는 것이 학습에 도움이 됩니다. 문제의 양이 어느 정도 되기 때문에 접기 기능을 이용하였습니다. 문제를 풀어보고 싶은 분은 아래의 문제보기 버튼을 누르시면 됩니다. ​

문제보기
[문제 1]

$$\begin{bmatrix}5 & 6 \\ 8 & 9\end{bmatrix}$$

[정답]
arr1[1:3,1:3]
arr1[[1,2],[1,2]]
arr1[[1,2],1:3]
arr1[[1,2],:][:,[1,2]]
arr1[np.ix_([1,2],[1,2])] ​
[문제 2]

[4,7] 추출


[정답]
arr1[1:3,0]
arr1[[1,2],0]
arr1[[1,2],:][:,0]
arr1[:,0][[1,2]]
~~arr1[:,0][[1,2],:] - 불가능, [:,0]이 1차원이기 때문에 뒤 색인도 반드시 1차원~~


다른 배열 arr2을 이용하여 다른 문제도 풀어봅시다.

arr2 = np.arange(1,25).reshape(2,3,4)
$$\begin{bmatrix}\begin{bmatrix}1 & 2 & 3 & 4\\5 & 6 & 7 & 8\\9 & 10 & 11 & 12\end{bmatrix}\\\begin{bmatrix}13 & 14 & 15 & 16\\17 & 18 & 19 & 20\\21 & 22 & 23 & 24\end{bmatrix}\end{bmatrix}$$
문제 3

$$\begin{bmatrix}10 & 11 \\ 14 & 15 \\ 18 & 19 \end{bmatrix}$$

[정답]​
arr2[2:5,1:3]
arr2[[2,3,4],:][:,[1,2]]
arr2[np.ix_([2,3,4],[1,2])]

문제 4

[ 6 7 8 ]추출


[정답] arr2[1,1:4]
arr2[1,:][[1,2,3]] ​

다음으로는 색인을 활용한 연산식을 만들어봅시다.
​​
문제 5
​​
arr1에서 첫번째 컬럼값을 추출,
각 컬럼마다 값을 더해 출력


[정답]
arr3 + arr3[:,0:1]



Transpose

다음으로는 배열의 행과 열 순서를 바꿔 주는 전치 메서드(transpose)라는 메서드입니다. 예를 들어, (2x3)의 배열을 (3x2)로 바꾸면


로 바꾸는 것을 의미합니다.

1. T : 행열을 서로 바꿉니다.

2. transpose : 괄호 안에 모든 축의 번호를 원하는 위치에 전달하면 축끼리 이동시킵니다., 축번호 전달 순서 중요합니다.

3. swapaxes : 괄호 안에 2개의 축 번호를 전달하면, 원하는 두 축의 전치를 수행하기 때문에 축 번호 전달 순서는 중요하지 않습니다.

입력 출력 형태
arr1
arr1.transpose(0,1)
array([[1, 2, 3],
         [4, 5, 6],
         [7, 8, 9]])
arr1.T
arr1.transpose(1,0)
arr1.swapaxes(0,1)
arr1.swapaxes(1,0)
array([[1, 4, 7],
         [2, 5, 8],
         [3, 6, 9]])



asarray

  • array로의 형 변환 함수입니다.

  • array와 달리 기본적으로 얕은 복사(shallow copy) 수행합니다.

예시) L1 = [1,2,3,4]

  출력 값 arr1[0] = 10
arr1 = np.array(L1) [1 2 3 4] [10 2 3 4]
arr2 = np.array(arr1)
(= arr1.copy())
[1. 2. 3. 4.] [1. 2. 3. 4.]
arr3 = np.asarray(arr1) [1. 2. 3. 4.] [10. 2. 3. 4.]
arr3 = np.asarray(
arr1, dtype = ‘float’)
[1. 2. 3. 4.] [1. 2. 3. 4.]
형 변환이 이루어지는 경우에는 딥카피(deep copy)



astype

  • 형 변환 함수로 배열(array)내의 원소를 한꺼번에 형 변환이 가능합니다. (벡터 연산 가능)


​ 예시 ) 다음의 배열의 타입을 실수로 변경

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


1) 형변환 함수 사용 (벡터연산 불가)

list(map(lambda x : float(x), arr1)) - mapping이 필요


2) 형변환 메소드 사용(벡터연산 가능)

arr1.astype(‘float’)



산술연산 함수

  • 배열(array)에 대한 산술연산에 있어서는 함수랑 메서드 모두 지원합니다.

​ 예시) arr1 = np.arange(1,10).reshape(3,3)

  메서드 함수
총합 arr1.sum() np.sum(arr1)
평균 arr1.mean() np.mean(arr1)
분산 arr1.var() np.var(arr1)
표준편차 arr1.std() np.std(arr1)


누적 산술연산

누적 산술연산은 행 혹은 열 방향으로 누적으로 산술연산을 진행하는 것을 말합니다.문법은 배열.cumsum(axis = 축 번호)인데 축 번호에 0을 입력하면 행 방향으로 연산이 진행되고 1을 입력하면 열 방향으로 연산이 진행됩니다. 덧셈과 곱셈만 가능합니다.

  누적 합
(arr1.cumsum)
누적 곱
(arr1.cumprod)
행 별
(axis = 0)
array([[ 1, 2, 3],
          [ 5, 7, 9],
          [12, 15, 18]],
          dtype=int32)
array([[ 1, 2, 3],
          [ 4, 10, 18],
          [ 28, 80, 162]],
          dtype=int32)
열 별
(axis = 1)
array([[ 1, 3, 6],
          [ 4, 9, 15],
          [ 7, 15, 24]],
          dtype=int32)
array([[ 1, 2, 6],
          [ 4, 20, 120],
          [ 7, 56, 504]],
          dtype=int32)



최대 최소값

arr1.max/min(축 번호)

축 별로 최댓값/최솟값을 출력한다

arr1.argmax/argmin(축 번호)

축 별로 최댓값/최솟값의 위치를 출력한다



조건 색인

조건 색인(Boolean indexing)은 조건에 맞는 데이터만 출력하는 것을 말합니다. 특정 값과 일치하는 데이터를 찾을 때 주의할 점이 있는데 연산자는 =가 아니라 == 입니다.

1. 논리 연산자 이용

#배열 내에서 5보다 큰 값 출력
arr1[arr1 > 5]
Out : [6, 7, 8, 9]

#세번째 컬럼의 값이 6인 행 선택
arr1[arr1[:,2] == 6,:]


#세번째 컬럼의 값이 6이 아닌 행 선택(not 논리연산)
arr1[arr1[:,2] != 6,:]
arr1[~(arr1[:,2] == 6),:]


2. np.where

numpy 모듈에 있는 where 함수는 조건의 벡터연산이 가능하게 하며 R의 ifelse 구문과 비슷한 기능을 합니다. 조건에 대한 단순리턴만 가능합니다.

문법 : np.where( 조건 , TRUE 출력값, FALSE 출력값)

#배열 내에서 5보다 큰 경우 A를 그렇지 않으면 B를 출력
np.where(arr3 > 5, 'A', 'B')


3. 불리언 배열 메서드 (boolean array method)

입력 설명
(arr2 > 10).sum() 조건에 만족하는 값의 개수
(arr2 > 10).any() 하나라도 조건을 만족하는지 여부(T or F)
(arr2 > 10).all() 모든 값이 조건을 만족하는지 여부(T or F)

집합 연산자

집합 연산자는 각 배열끼리 집합 연산을 하는 기능을 가지고 있습니다.

  1. union1d : 합집합     / (A U B)

  2. intersect1d : 교집합 / (A ∩ B)

  3. setdiff1d : 차집합    / (A - B)

  4. in1d : 포함연산자

  5. setxor1d : 대칭차집합 / (A-B) U (B-A)

예)

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

arr2 = np.array([3,4,5,6])

메서드 출력 값
np.union1d(arr1,arr2) array([1, 2, 3, 4, 5, 6])
np.intersect1d(arr1,arr2) array([3, 4])
np.setdiff1d(arr1,arr2) array([1, 2])
np.in1d(arr1,arr2) array([False, False, True, True])
np.setxor1d(arr1,arr2) array([1, 2, 5, 6])


(+) np.unique(배열) : 모든 원소중에 중복을 제외하고 유일한 값들만 출력하는 함수입니다.

np.unique(np.array([1,1,1,2]))
Out : [1,2]

NaN

  • NaN(Not a Number)은 표현 불가능한 수치형 결과를 나타내는 값으로 자기 자신과도 일치하지 않습니다.

  • R과 달리 Python에 기본으로 있지 않기 자료형이 아니기 때문에 NaN을 사용하기 위해서는 모듈 numpy를 불러와야 합니다.

  • 기본적으로 nan으로 출력되나 편의를 위해서 이 블로그에서는 NA를 Alias로 사용할 것입니다.

#nan을 NA로 Alias 설정
from numpy import nan as NA   

1. 원소를 NaN으로 수정

  • 수치형 자료지만 float 형식에서만 사용할 수 있으며 정수로 된 자료 구조에서는 사용할 수 없습니다.
arr1 = np.array([1,2,3,4])

arr1[0] = NA 
Traceback (most recent call last):

  File "<ipython-input-5-eeac312552ee>", line 1, in <module>
    arr1[0] = NA

ValueError: cannot convert float NaN to integer
정수로 된 배열에 들어가지 않는 NaN

  • float으로 바꾸는 방법
# 1. map함수 이용
list(map(lambda x : float(x), arr1))
# 2. astype 이용
arr1 = arr1.astype('float')

# float 변경 이후 NA 입력
arr1[0] = NA ; arr1
Out : array([nan,  2.,  3.,  4.])


2. NA 있는지 확인(벡터 연산 가능)

np.isnan([1,2,NA,3])
Out : array([False, False, True, False])


여기까지는 모듈 numpy, 자료 구조 배열(array) 그리고 NaN에 대해 다뤄보았습니다. 다음 포스트에는 모듈 pandas와 자료 구조 시리즈(Series)데이터프레임(DataFrame)에 대해 다뤄보도록 하겠습니다.​