Idealim
article thumbnail

/* 본 게시물은 ' 파이썬 라이브러리를 활용한 데이터 분석 2판 | with 웨스 맥키니 ' 의 내용과 참고자료를 토대로 작성되었습니다. */

/* 본 글은 개인적으로 공부한 내용을 정리한 글이므로 오류가 있을 수 있습니다. */


배열지향 프로그래밍

Numpy 배열을 사용하면 반복문을 작성하지 않고 간결한 배열 연산을 사용해 많은 종류의 데이터 처리 작업을 할 수 있다. 배열 연산을 사용해서 반복문을 명시적으로 제거하는 기법을 벡터화라 부른다. 일반적으로 벡터화된 배열에 대한 산술 연산은 순수 파이썬 연산에 비해 처리 시간이 빠르다. 배열 연산을 하는 방법에 대해 알아보자.


1. 배열 연산으로 조건절 표현하기

numpy.where 함수는 x if 조건 else y 같은 삼항식의 벡터화된 버전이다. 다음과 같은 불리언 배열 하나와 값이 들어 있는 두 개의 배열이 있다고 하자.

Data

xarr = np.array([1.1, 1.2, 1.3, 1.4, 1.5])
yarr = np.array([2.1, 2.2, 2.3, 2.4, 2.5])
cond = np.array([True, False, True, True, False])

파이썬 조건문을 이용한 배열 처리

result = [(x if c else y) for x ,y ,c in zip(xarr, yarr, cond)]
print(result) # [1.1, 2.2, 1.3, 1.4, 2.5]

위 방법은 파이썬의 리스트 표기법을 이용한 배열 처리 방법이다. 이 방법은 순수 파이썬으로 실행되기 때문에 큰 배열을 빠르게 처리하지 못한다. 또한 다차원 배열에서는 사용할 수 없는 문제가 있다. 이를 해결하기 위해 np.where 를 사용한다.

np.where 를 이용한 배열 처리

result = np.where(cond, xarr, yarr)
print(result) #[1.1 2.2 1.3 1.4 2.5]

파이썬 조건문을 이용한 배열 처리 코드를 위 코드 처럼 바꿔 사용할 수 있다. np.where 의 첫 번째 인자로는 condition , 두 번째 인자로는 x, 세번째 인자로는 y 를 취한다. 이 때 x 와 y는 스칼라 값이어도 상관없다. 예시를 통해 알아보자.

arr = np.random.randn(4,4)
print(arr)
"""
[[ 1.14346175 -0.25972026 -0.32073818  1.09493051]
 [ 1.21113214 -0.74069361  0.03328632 -0.46109669]
 [-2.27463094  0.20017768 -0.21944185 -0.11763948]
 [ 0.20343772 -1.58394208  1.16629969  0.07038985]]
"""
result = np.where(arr > 0, 2, -2) # 양수 일 때 2 , 음수 일 때 -2
print(result)
"""
[[ 2 -2 -2  2]
 [ 2 -2  2 -2]
 [-2  2 -2 -2]
 [ 2 -2  2  2]]
"""
result = np.where(arr > 0, arr, -2) # 음수 일 때만 -2
print(result)
"""
[[ 1.14346175 -2.         -2.          1.09493051]
 [ 1.21113214 -2.          0.03328632 -2.        ]
 [-2.          0.20017768 -2.         -2.        ]
 [ 0.20343772 -2.          1.16629969  0.07038985]]
"""

즉, np.where 로 넘기는 x, y 는 크기만 같은 배열이거나 스칼라 값이 될 수 있다.


2. 수학 메서드와 통계 메서드

배열 전체 혹은 배열에서 한 축을 따르는 자료에 대한 통계를 계산하는 수학 함수는 배열 메서드로 사용할 수 있다. 전체의 합(sum) 이나 평균(mean), 표준편차(std) 는 Numpy 의 최상위 함수를 이용하거나 배열의 인스턴스 메서드를 사용해서 구할 수 있다.

기본 배열 통계 메서드

메서드 설명
sum 배열 전체 혹은 특정 축에 대한 모든 원소의 합을 계산한다. 
mean 산술 평균을 구한다.
std, var 각각 표준편차와 분산을 구한다. 선택적으로 자유도를 줄 수 있으며 분모의 기본값은 n이다.
min, max 최솟값, 최댓값
argmin, argmax 최소 원소의 색인값, 최대 원소의 색인값
cumsum 각 원소의 누적합
cumprod 각 원소의 누적곱

Numpy 최상위 함수 / 배열 인스턴스 메서드

Data

arr = np.random.randn(5, 4)
"""
[[-0.47666934  0.94950758  1.40421027  3.50000699]
 [-0.09310364  1.63422602 -0.47835861  1.71115569]
 [-0.55269564 -1.04166738 -0.94379122 -0.05021702]
 [-0.78447515  1.00185074 -1.24156519 -1.09167689]
 [ 0.51867498 -1.08927922  0.54408462  0.25952535]]
"""
# Numpy 최상위 함수 mean()
print(np.mean(arr))
# 배열 인스턴스 메서드
print(arr.mean())

"""
0.18398714649437548
0.18398714649437548
"""

mean, sum

선택적으로 axis 인자를 받아서 해당 axis에 대한 통계를 계산하고 한 차수 낮은 배열을 반환한다.

Data

arr = np.arange(12).reshape(3,4)
"""
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
"""
print(arr.mean(axis = 1)) # row mean
print(arr.mean(axis = 0)) # column mean
"""
[1.5 5.5 9.5] # row mean
[4. 5. 6. 7.] # column mean
"""
print(arr.sum(axis = 1)) # row sum
print(arr.sum(axis = 0)) # column sum
"""
[ 6 22 38] # row sum
[12 15 18 21] # column sum
"""

axis = 1 은 row 끼리 계산 0은 column 끼리 계산한다.

cumsum, cumprod

각 원소의 누적합 / 누적곱, 중간 계산값을 담고 있는 배열을 반환한다.

Data

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

cumsum

print(arr.cumsum(axis = 0)) # column sum
"""
[[ 0  1  2]
 [ 3  5  7]
 [ 9 12 15]]
"""
print(arr.cumsum(axis = 1)) # row sum
"""
[[ 0  1  3]
 [ 3  7 12]
 [ 6 13 21]]
"""

cumprod

print(arr.cumprod(axis = 0))
"""
[[ 0  1  2]
 [ 0  4 10]
 [ 0 28 80]]
"""
print(arr.cumprod(axis = 1))
"""
[[  0   0   0]
 [  3  12  60]
 [  6  42 336]]
"""

argmin, argmax 

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

cf > max ,min / argmax ,argmin 차이 

y = f(x) 라고 할 때,
max는 y가 최대인 값, argmax는 y를 최대가 되도록 하는 x
min은 y가 최소인 값, argmin은 y를 최소가 되도록 하는 x

Data

arr = np.random.randn(5, 4)
"""
[[ 0.75812153 -1.23647362 -0.12649955 -0.33715864]
 [-1.75065862 -0.35726469  0.21861309 -1.88279934]
 [ 0.4265068   0.34793345  0.92665941 -1.61469999]
 [ 0.54528009 -0.51474162 -0.76916919 -0.28098776]
 [ 1.40019948  1.46111942  1.19026401  1.40834521]]
"""

argmin / argmax

print(arr.argmin()) # 7
print(arr.argmax()) # 17

좌표가 아닌 색인값(스칼라값)으로 반환한다.


3. 불리언 배열을 위한 메서드

Data 

arr = np.random.randn(100)

Sum 메서드를 이용한 원소의 개수 세기

print((arr > 0).sum()) # 0 보다 큰 값들의 합

any / all

bools = np.array([False, False, True, False])
# any : 하나 이상의 값이 True 인지 검사
print(bools.any()) # True
# all : 모든 원소가 True 인지 검사
print(bools.all()) # False

4. 정렬

 

정렬 방법도 배열의 인스턴스 메서드를 이용한 방법과 Numpy 의 sort 함수를 이용한 방법이 있다.

인스턴스 메서드 sort

Data

arr = np.random.randn(5,3)
arr2 = arr.copy()
"""
[[-0.18977479 -0.56907074  1.9338289 ]
 [-0.74356722 -0.35169774  0.84739729]
 [-0.44211294 -1.49183426 -0.33539884]
 [ 1.01193049 -0.79934212 -1.31787391]
 [ 0.22301143  1.26795106  0.44107973]]
"""
arr.sort() # row sorting
print(arr)
"""
[[-0.56907074 -0.18977479  1.9338289 ]
 [-0.74356722 -0.35169774  0.84739729]
 [-1.49183426 -0.44211294 -0.33539884]
 [-1.31787391 -0.79934212  1.01193049]
 [ 0.22301143  0.44107973  1.26795106]]
""
arr2.sort(0) # column sorting
print(arr2)
"""
[[-0.74356722 -1.49183426 -1.31787391]
 [-0.44211294 -0.79934212 -0.33539884]
 [-0.18977479 -0.56907074  0.44107973]
 [ 0.22301143 -0.35169774  0.84739729]
 [ 1.01193049  1.26795106  1.9338289 ]]
"""

인스턴스 메서드 sort 를 이용하면 기존 배열을 정렬한다. sort 의 default 값(1)은 row 이고 column 기준으로 정렬하고 싶으면 인자로 0을 주면 된다.

np.sort()

배열을 직접 변경하지 않고 정렬된 결과를 가지고 있는 새 배열을 반환한다.

arr = np.random.randn(5,3)
print(arr)
"""
[[-1.48505274  0.99118431  0.44552078]
 [-0.78755978  1.39665918 -0.45583582]
 [ 0.20736073 -1.03474508 -0.20544616]
 [ 1.04847923  0.48018452 -0.39134499]
 [ 0.89725373 -0.75147547 -0.1301517 ]]
"""
print(np.sort(arr))
"""
[[-1.48505274  0.44552078  0.99118431]
 [-0.78755978 -0.45583582  1.39665918]
 [-1.03474508 -0.20544616  0.20736073]
 [-0.39134499  0.48018452  1.04847923]
 [-0.75147547 -0.1301517   0.89725373]]
"""
print(arr)
"""
[[-1.48505274  0.99118431  0.44552078]
 [-0.78755978  1.39665918 -0.45583582]
 [ 0.20736073 -1.03474508 -0.20544616]
 [ 1.04847923  0.48018452 -0.39134499]
 [ 0.89725373 -0.75147547 -0.1301517 ]]
"""

5. 집합 관련 함수

Numpy는 1차원 ndarray를 위한 몇 가지 기본적인 집합 연산을 제공한다. 

배열 집합 연산

메서드 설명
unique(x) 배열 x에서 중복된 원소를 제거한 뒤 정렬하여 반환한다.
intersect1d(x, y) 배열 x 와 y에 공통적으로 존재하는 원소를 정렬하여 반환한다.
union1d(x, y) 두 배열의 합집합을 반환한다.
in1d(x, y) x의 원소가 y의 원소에 포함되는지 나타내는 불리언 배열을 반환한다.
setdiff1d(x, y) x와 y의 차집합을 반환한다.
setxor1d(x, y) 한 배열에는 포함되지만 두 배열 모두에는 포함되지 않는 원소들의 집합인 대칭차집합을 반환한다.

unique / in1d example

arr = np.array([1,2,3,4,3,2,1])
unique = np.unique(arr)
print(unique)
"""
[1 2 3 4]
"""

#sorted() 를 사용한 unique() 구현 -> List 반환
print(sorted(set(arr)))
"""
[1, 2, 3, 4]
"""
# np.in1d : 두 개의 배열을 인자로 받아서 첫 번째 배열의 원소가 두 번째 배열의 원소를 포함하는 나타내는 불리언 배열을 반환
values = np.array([6, 0, 0, 3, 2, 5, 6])
print(np.in1d(values, [2, 3, 6])) 
"""
[ True False False  True  True False  True]
"""

참고 자료

[URL] :

반응형
profile

Idealim

@Idealim

읽어주셔서 감사합니다. 잘못된 내용이 있으면 언제든 댓글로 피드백 부탁드립니다.