이번 포스팅에서는 Python의 numpy 라이브러리에 있는 함수들을 이용해서 두 개의 배열(array)을 옆으로 붙이기, 배열을 위 아래로 붙이기(concatenate) 하는 방법에 대해서 소개하겠습니다.  알아두면 편리하게 배열을 조작할 수 있는 유용한 함수들입니다. 


(1) 두 배열을 왼쪽에서 오른쪽으로 붙이기 

   : np.r_[a, b]

   : np.hstack([a, b])


(2) 두 배열을 위에서 아래로 붙이기

   : np.r_[[a], b]

   : np.vstack([a, b])


(3) 두 개의 1차원 배열을 칼럼으로 세로로 붙여서 2차원 배열 만들기

    (Stack 1-D arrays as columns into a 2-D array)

   : np.c_[a, b]

   : np.column_stack([a, b])



 [ 배열을 옆으로, 위 아래로 붙이기 : np.r_, np.c_, np.hstack(), np.vstack(), np.column_stack() ]




처음에 np.r_[a, b], np.c_[a, b] 코드를 봤을 때 '이게 뭐지?', '잘못 타이핑한거 아닌가?', '쓰다 말았나?' 하고 갸우뚱 했던 기억이 납니다. ^^; 


아래에 간단한 예를 들어서 설명하겠습니다. 

np.r_[], np.c_[] 는 코드가 완전 간단한 장점이 있구요, np.hstack(), np.vstack(), np.column_stack() 는 코드 이해가 쉬운 장점이 있는데요, 코드 작성하시는 분의 선호도에 따라 골라 쓰시면 되겠습니다. 


먼저 numpy 라이브러리 importing 한 후에 a, b 두 개의 예제 배열(array)을 만들겠습니다. 



In [1]: import numpy as np


In [2]: a = np.array([1, 2, 3])


In [3]: b = np.array([4, 5, 6])


 



(1) 두 배열을 왼쪽에서 오른쪽으로 붙이기 

   : np.r_[a, b]     <- ( ) 를 사용하지 않고 [ ] 를 사용하는 것에 주의하세요

   : np.hstack([a, b])


 

 In [4]: np.r_[a, b]

 Out[4]: array([1, 2, 3, 4, 5, 6])


 In [7]: np.hstack([a, b])

 Out[7]: array([1, 2, 3, 4, 5, 6])



(2) 두 배열을 위에서 아래로 붙이기

   : np.r_[[a], b]   <- a 배열을 [ ]을 사용해서 1-D 배열로 만든거 주의하세요

   : np.vstack([a, b])



In [5]: np.r_[[a], [b]]

Out[5]:

array([[1, 2, 3],

        [4, 5, 6]])

 


In [8]: np.vstack([a, b])

Out[8]:

array([[1, 2, 3],

        [4, 5, 6]])

 



(3) 두 개의 1차원 배열을 칼럼으로 세로로 붙여서 2차원 배열 만들기

    (Stack 1-D arrays as columns into a 2-D array)

   : np.c_[a, b]

   : np.column_stack([a, b])



In [6]: np.c_[a, b]

Out[6]:

array([[1, 4],

        [2, 5],

        [3, 6]])

 


In [9]: np.column_stack([a, b])

Out[9]:

array([[1, 4],

        [2, 5],

        [3, 6]])



많은 도움이 되었기를 바랍니다. 

이번 포스팅이 도움이 되셨다면 아래의 '공감~'를 꾸욱 눌러주세요. ^^



Posted by R Friend R_Friend

이번 포스팅에서는 파이썬에서 다차원 배열(array)을 1차원 배열로 평평하게 펴주는 NumPy의 ravel() 함수에 대해서 알아보겠습니다. 


1차원 배열을 다차원 배열로 재구성/재배열 해주는 NumPy의 reshape() 함수와 반대의 기능을 하는 함수가 ravel() 이라고 보시면 되겠습니다. 


기계학습 알고리즘 학습하다보면 가끔씩 ravel() 함수가 나오는데요, 이참에 order 옵션 'C', 'F', 'K' 별 기능에 대해서도 정리해서 알아두면 좋을 듯 합니다. 


[ Python NumPy ravel() 함수 vs. reshape() 함수 ]




-- 2차원 배열 -- 


먼저 0 ~ 11 까지의 12개의 원소로 이루어진 3 x 4 배열을 만들어 보겠습니다.  



In [1]: import numpy as np

   ...: x = np.arange(12).reshape(3, 4)

   ...: x

   ...:

Out[1]:

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

        [ 4, 5, 6, 7],

        [ 8, 9, 10, 11]])




위에서 만든 2차원 배열에 대해서 order='C', order='F', order='k'별로 순서대로 위의 배열 3*4 배열 x가 어떤 순서대로 평평하게 펴지는지 예제로 살펴보겠습니다. 


(1) np.ravel(x, order='C') : C와 같은 순서로 인덱싱하여 평평하게 배열 (디폴트)



In [2]: np.ravel(x, order='C') # by default

   ...:

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

 




(2) np.ravel(x, order='F') : Fortran과 같은 순서로 인덱싱하여 평평하게 배열



In [3]: np.ravel(x, order='F')

   ...:

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

 




 (3) np.ravel(x, order='K') : 메모리에서 발생하는 순서대로 인덱싱하여 평평하게 배열



In [4]: np.ravel(x, order='K')

   ...:

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





-- 3차원 배열 -- 


3차원 이상의 배열에 대해서도 ravel() 함수를 사용해서 1차원 배열로 평평하게 펼 수가 있습니다. 이때 order 매개변수를 설정해줄 때 조금 주의가 필요합니다. 아래에 2*3*2 의 3차원 배열에 대해서 축이 어떻게 설정되어있느냐(배열 순서가 어떤가)에 따라서 order='C'와 order='K'를 선택해서 사용하면 되겠습니다. 


(4) np.raver(y, order='C') : 3차원 배열의 평평하게 펴기



In [5]: y = np.arange(12).reshape(2, 3, 2)

   ...: y

Out[5]:

array([[[ 0, 1],

         [ 2, 3],

         [ 4, 5]],


        [[ 6, 7],

         [ 8, 9],

         [10, 11]]])

 



In [6]: np.ravel(y, order='C')

   ...:

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

 




 (5) np.ravel(z, order='K') : 축이 바뀐 3차원 배열을 평평하게 펴기



In [7]: z = np.arange(12).reshape(2, 3, 2).swapaxes(1, 2)


In [8]: z

Out[8]:

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

         [ 1, 3, 5]],


        [[ 6, 8, 10],

         [ 7, 9, 11]]])

 



In [9]: np.ravel(z, order='K')

   ...:

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

 



이상으로 다차원 배열을 1차원 배열로 평평하게 펴주는 numpy.ravel(a, order='C', 'F', 'K') 함수에 대해서 알아보았습니다. 


많은 도움이 되었기를 바랍니다. 

이번 포스팅이 도움이 되었다면 아래의 '공감~'를 꾸욱 눌러주세요. ^^



Posted by R Friend R_Friend

파이썬 NumPy 에서 배열의 차원(Dimension)을 재구조화, 변경하고자 할 때 reshape() 메소드를 사용합니다.  가령, 3개의 행과 4개의 열로 구성된 2차원의 배열로 재설정하고 싶으면 reshape(3, 4) 처럼 reshape()의 매개변수로 변경하고자 하는 배열의 행과 열의 차원을 정수로 입력해주면 됩니다. 


그런데 reshape(-1, 2) 혹은 reshape(3, -1) 처럼 reshape() 메소드 안에 '-1'이 들어가 있는 경우가 있습니다. 이때 reshape()의 '-1'이 의미하는 바는, 변경된 배열의 '-1' 위치의 차원은 "원래 배열의 길이와 남은 차원으로 부터 추정"이 된다는 뜻입니다. (One shape dimension can be -1. In this case, the value is inferred from the length of the array and remaining dimensions.)


말이 좀 어렵고, 금방 이해하기가 쉽지 않은데요, ^^; 아래에 간단한 예를 들어서 설명해보겠습니다. 


먼저 NumPy 라이브러리를 import 하고 3x4 차원의 예제 배열을 만들어보겠습니다. 

(우리가 일상적으로 사용하는 reshape() 의 사용 예제)



In [1]: import numpy as np


In [2]: x = np.arange(12).reshape(3, 4)


In [3]: x.shape

Out[3]: (3, 4)


In [4]: x

Out[4]:

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

        [ 4, 5, 6, 7],

        [ 8, 9, 10, 11]])

 



  (1) reshape(-1, 정수) 의 행(row) 위치에 '-1'이 들어있을 경우


이제 reshape() 의 행(row) 차원 위치에 '-1'을 넣으면 어떻게 재구조화가 되는지 살펴보겠습니다. 

총 12개의 원소가 들어있는 배열 x에 대해서 x.reshape(-1, 정수) 를 해주면 '열(column)' 차원의 '정수'에 따라서 12개의 원소가 빠짐없이 배치될 수 있도록 '-1'이 들어가 있는 '행(row)' 의 개수가 가변적으로 정해짐을 알 수 있습니다.  


x.reshape(-1, 1)

=> shape(12,1)

x.reshape(-1, 2

=> shape(6, 2)

 x.reshape(-1, 3)

=> shape(4, 3)

x.reshape(-1, 4

=> shape(34)

 

In [5]: x.reshape(-1, 1)

Out[5]:

array([[ 0],

        [ 1],

        [ 2],

        [ 3],

        [ 4],

        [ 5],

        [ 6],

        [ 7],

        [ 8],

        [ 9],

        [10],

        [11]])


 In [6]: x.reshape(-1, 2)

Out[6]:

array([[ 0, 1],

        [ 2, 3],

        [ 4, 5],

        [ 6, 7],

        [ 8, 9],

        [10, 11]])







 In [7]: x.reshape(-1, 3)

Out[7]:

array([[ 0, 1, 2],

        [ 3, 4, 5],

        [ 6, 7, 8],

        [ 9, 10, 11]])









 In [8]: x.reshape(-1, 4)

Out[8]:

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

        [ 4, 5, 6, 7],

        [ 8, 9, 10, 11]])













  (2) reshape(정수, -1) 의 열(column) 위치에 '-1'이 들어있을 경우


다음으로 reshape()의 열(column) 위치에 '-1'을 넣으면 어떻게 재구조화되는지 살펴보겠습니다. 

x의 총 원소 12개가 모두 배열될 수 있도록 행(row)의 정수가 정해지면, 이에 따라서 '-1'이 들어있는 열(column)의 개수가 정해짐을 알 수 있습니다. 


즉, 행이나 열의 특정 차원을 기준으로 재배열하고 싶은 행이나 열의 개수가 있으면 나머지 차원의 개수는 '-1'로 해두면 알아서 자동으로 재배열을 해주니 편리한 기능이라고 하겠습니다. 


x.reshape(1, -1)

  => shape(1, 12)

 

In [9]: x.reshape(1, -1)

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


 x.reshape(2, -1)

  => shape(2, 6)

 

In [10]: x.reshape(2, -1)

Out[10]:

array([[ 0, 1, 2, 3, 4, 5],

        [ 6, 7, 8, 9, 10, 11]])


 x.reshape(3, -1)

  => shape(3, 4)

 

In [11]: x.reshape(3, -1)

Out[11]:

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

        [ 4, 5, 6, 7],

        [ 8, 9, 10, 11]])


 x.reshape(4, -1)

  => shape(4, 3)


In [12]: x.reshape(4, -1)

Out[12]:

array([[ 0, 1, 2],

        [ 3, 4, 5],

        [ 6, 7, 8],

        [ 9, 10, 11]])





  (3) reshape(-1) 인 경우


x.reshape(-1)은 x.reshape(1, -1)과 같이 1차원 배열을 반환합니다. 


x.reshape(-1)

 

In [13]: x.reshape(-1)

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


 x.reshape(1, -1)

 

x.reshape(1, -1)

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





  (4) ValueError: cannot reshape array of size 12 into shape (5)


reshape(-1, 정수) 또는 reshape(정수, -1) 메소드가 제대로 작동하기 위해서는 한가지 조건이 있는데요, 원래의 배열에 있는 원소가 재구조화 혹은 재배열 되려는 배열의 차원에 빠짐없이 분배가 될 수 있어야 한다는 점입니다.  


가령, 위의 (1), (2), (3)번 예에서는 12개의 원소로 구성된 x배열을 (1, 12), (2, 6), (3, 4), (4, 3) 으로 재배열했었습니다. 하지만 아래의 ValueError 가 난 것처럼 12개의 원소로 구성된 원래의 배열 x에 대해 x.reshape(-1, 5) 혹은 x.reshape(7, -1) 로 재구조화하려고 하면 서로 호환이 안되기 때문에 ValueError가 난 것입니다. 



In [15]: x.reshape(-1, 5)

Traceback (most recent call last):


File "<ipython-input-15-3341ca33497d>", line 1, in <module>

x.reshape(-1, 5)


ValueError: cannot reshape array of size 12 into shape (5)

In [16]: x.reshape(7, -1)

Traceback (most recent call last):


File "<ipython-input-16-c8e97ae7c9bc>", line 1, in <module>

x.reshape(7, -1)


ValueError: cannot reshape array of size 12 into shape (7,newaxis)

 




  (5) ValueError: can only specify one unknown dimension


reshape(-1, -1)은 행, 열 어느 차원도 정해주지 않았으므로 ValueError 가 발생합니다. 



In [17]: x.reshape(-1, -1)

Traceback (most recent call last):


File "<ipython-input-17-8142d87a8f95>", line 1, in <module>

x.reshape(-1, -1)


ValueError: can only specify one unknown dimension

 



많은 도움이 되었기를 바랍니다. 


이번 포스팅이 도움이 되었다면 아래의 '공감~'를 꾹 눌러주세요. ^^



Posted by R Friend R_Friend

그동안 Python NumPy의 단일 배열 unary ufuncs 에 대해서 알아보았습니다.

(http://rfriend.tistory.com/300, http://rfriend.tistory.com/301)

 

이번 포스팅에서는 그동안 배웠던 unary ufuncs 들을 요리조리 조합하고 응용하는 한가지 예를 들어보겠습니다.

 

- 절대값을 구하는 함수 np.abs(x)

- 배열 원소의 부호를 판별하는 np.sign(x) 함수

- 배열의 1개 이상의 원소가 참(True) 인지 평가하는 np.any(x) 함수

 

를 이용해서 특이값, 이상치(outlier)를 탐색하고, indexing해서 다른 값으로 대체하는 방법을 소개하겠습니다.

 

 

먼저 numpy, pandas, matplotlib.pyplot 모듈을 불러오고, 평균이 0, 표준편차가 1인 정규분포로 부터 난수 10,000만개를 생성해보겠습니다.

 

 

In [1]: import numpy as np

   ...: import pandas as pd

   ...: import matplotlib.pyplot as plt

   ...:


In [2]: np.set_printoptions(precision=2)

   ...:

   ...: # setting random seed number

   ...: np.random.seed(10)

   ...:

   ...: # random number 10000 ~ N(0, 1)

   ...: mu, sigma = 0, 1

   ...: x = pd.DataFrame(mu + sigma*np.random.randn(10000))

 

 

 

 

다음으로 dexcribe() 메서드를 사용해서 x의 기술통계량을 알아보고, 히스토그램으로 분포를 살펴보겠습니다. min과 max 값을 보면 평균 0을 중심으로 해서 -3 (-3 sigma)과 +3 (+3 sigma)을 벗어나는 관측치가 있음을 알 수 있습니다.

 

 

# checking descriptive statistics and histogram

In [3]: x.describe()

Out[3]:

0

count 10000.000000

mean 0.005102

std 0.989713

min -3.621639

25% -0.652208

50% 0.013111

75% 0.675040

max 3.691489


In [4]: plt.hist(x)

Out[4]:

(array([ 15., 139., 583., 1626., 2733., 2679., 1606., 497.,

107., 15.]),

array([-3.62, -2.89, -2.16, ..., 2.23, 2.96, 3.69]),

<a list of 10 Patch objects>)

 

 

 

 

 

정규분포를 띠는 데이터셋의 경우 평균으로 부터 +3 sigma, -3 sigma 를 벗어나는 데이터의 경우 전체 데이터셋 중 99%가 존재하는 구간을 벗어나는 특이값, 이상값(outlier)로 간주할 수 있습니다.

 

이번 예제에서 x는 평균이 '0'이고 표준편차가 '1'인 정규분포를 따르므로, np.abs(x)와 any(1) 함수를 조합해서 사용하면 1만개의 관측치를 가지는 x로부터 +- 3 sigma를 벗어나는 특이값만 쏙 빼올 수 있습니다.  count() 메소드로 특이값 개수도 세볼 수 있구요.

 

 

# indexing outlier rows over mu + 3sigma, less mu - 3 sigma

In [5]: x[(np.abs(x) > 3).any(1)]

   ...:

Out[5]:

0

412 -3.204401

1036 -3.317669

1558 -3.112645

2190 3.609161

3948 3.454845

4912 -3.372347

5016 -3.393109

5158 3.193371

5618 3.177053

5750 3.158873

6135 3.077068

6303 3.142285

6689 -3.621639

6760 3.027240

6986 -3.303552

7353 -3.214030

7892 3.561219

8281 3.691489

9179 3.286370

9335 3.503309

 

# counting the number of outliers

In [6]: x[(np.abs(x) > 3).any(1)].count()

Out[6]:

0 20

dtype: int64

 

 

 

 

이번에는 np.sign(x) 함수를 곁들여 사용하여 +- 3 sigma를 벗어나는 관측치값을 모두 +-3 으로 대체해보겠습니다. (즉, +3 sigma보다 큰 특이값은 +3으로 대체, -3 sigma 보다 작은 특이값은 -3으로 대체) 

 

x.describe()로 요약통계량을 살펴보니 min -3, max 3으로 바뀌었지요? 히스토그램도 -3 ~ +3 까지 분포로 바뀌었구요.

 

 

In [7]: x[np.abs(x) > 3] = np.sign(x)*3


In [8]: x[(np.abs(x) >= 3).any(1)]

Out[8]:

0

412 -3.0

1036 -3.0

1558 -3.0

2190 3.0

3948 3.0

4912 -3.0

5016 -3.0

5158 3.0

5618 3.0

5750 3.0

6135 3.0

6303 3.0

6689 -3.0

6760 3.0

6986 -3.0

7353 -3.0

7892 3.0

8281 3.0

9179 3.0

9335 3.0


In [9]: x.describe()

Out[9]:

0

count 10000.000000

mean 0.004968

std 0.987624

min -3.000000

25% -0.652208

50% 0.013111

75% 0.675040

max 3.000000


In [10]: plt.hist(x)

Out[10]:

(array([ 76., 292., 755., 1554., 2269., 2299., 1648., 762.,

277., 68.]),

array([-3. , -2.4, -1.8, ..., 1.8, 2.4, 3. ]),

<a list of 10 Patch objects>)

 

 

 

통계 분포 방법 외에 특이값 찾는 방법이 서너가지 더 있는데요, 그건 다음번에 기회 될 때 별도로 포스팅을 하겠습니다. (언제가 될지는 기약 못하겠네요. ^^;)

 

많은 도움 되었기를 바랍니다.

 

Posted by R Friend R_Friend

이전 포스팅에서는
 
 - 범용함수(universal function, ufuncs)의 정의 및 유형
 
 
(1) 1개의 배열에 대한 ufuncs (Unary universal functions) 중에서
 
 - (1-1) 올림 및 내림 범용 함수 (rounding ufuncs)
 - (1-2) 합(sums), 곱(products), 차분(difference), 기울기(gradient) 범용함수
 - (1-3) 지수함수(exponential function), 로그함수 (logarithmic function)

 - (1-4) 삼각함수(trigonometric functions) 

 - (1-5) 절대값(absolute), 제곱근(square root), 제곱값(square), 정수와 소수점 값 분리(integral and fractional parts), 부호(sign) 판별 함수

 

등에 대해서 알아보겠습니다.

 

 

이번 포스팅에서는 (1-6) 1개 배열 대상의 논리 범용 함수(Logic Unary ufuncs) 에 대해서 알아보겠습니다. 논리 함수(logic functions)는 참(True) 또는 거짓(False)의 boolean 값을 반환합니다.

 

 

 

 

 

  (1-6-1) 배열의 원소에 대한 논리 함수 (logic functions for array contents)

 

  (1-6-1-1) 배열에 NaN(Not a Number) 포함 여부 확인 함수 : np.isnan(x)

 

 

# isnan : Test element-wise for NaN(Not a Number) and return result as a boolean array

 

In [1]: import numpy as np


In [2]: a = np.array([0, 1, 2, np.nan, 4, np.inf, np.NINF, np.PINF])


In [3]: a

Out[3]: array([ 0., 1., 2., nan, 4., inf, -inf, inf])


In [4]: np.isnan(a)

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

 

 

 

 

  (1-6-1-2) 배열에 유한수(finite number) 포함 여부 확인 함수 : np.isfinite(x)

 

 

# isfinite : Test element-wise for finiteness (not infinity or not Not a Number)

 

In [5]: a

Out[5]: array([ 0., 1., 2., nan, 4., inf, -inf, inf])


In [6]: np.isfinite(a)

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

 

 

 

 

 (1-6-1-3) 배열에 무한수(infinite number) 포함 여부 확인 함수 : np.isinf(x)

 

 

# isinf : Test element-wise for positive or negative infinity

 

In [7]: a

Out[7]: array([ 0., 1., 2., nan, 4., inf, -inf, inf])

 

In [8]: np.isinf(a)

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

 

 

 

 

  (1-6-1-4) 배열에 음의 무한수 포함 여부 : np.isneginf(x)

 

 

# isneginf : Test element-wise for negative infinity, return result as bool array

 

In [9]: a

Out[9]: array([ 0., 1., 2., nan, 4., inf, -inf, inf])

 

In [10]: np.isneginf(a)

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

 

 

 

 

  (1-6-1-5) 배열에 양의 무한수 포함 여부 확인 함수 : np.isposinf(x)

 

 

# isposinf : Test element-wise for positive infinity, return result as bool arry

 

In [11]: a

Out[11]: array([ 0., 1., 2., nan, 4., inf, -inf, inf])

 

In [12]: np.isposinf(a)

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

 

 

 

 

  (1-6-2) 참 확인 논리 함수 (Logic functions for truth value testing)

 

  (1-6-2-1) 배열의 모든 원소가 참(True) 인지 평가하는 함수 : np.all()

 

축(no axis, axis=0, axis=1) 에 따라서 어떻게 참(True) 여부를 평가하는지 유심히 보시기 바랍니다.

 

 

# np.all() : Test whether all array elements along a given axis evaluate to True

 

In [13]: np.all([[True,False],[True,True]])

Out[13]: False


In [14]: np.all([[True,False],[True,True]], axis=0)

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

 

In [15]: np.all([[True,False],[True,True]], axis=1)

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

 

 

 

 

  (1-6-2-2) 배열의 1개 이상의 원소가 참(True) 인지 평가하는 함수 : np.any()

 

 

# np.any() : Test whether any array elements along a given axis evaluate to True

 

In [16]: np.any([[True,False],[True,True]])

Out[16]: True


In [17]: np.any([[True,False],[True,True]], axis=0)

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


In [18]: np.any([[True,False],[True,True]], axis=1)

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

 


 

In [21]: np.any([[False,False],[True,True]], axis=0)

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

 

In [22]: np.any([[False,False],[True,True]], axis=1)

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

 

 

 

 

  (1-6-3) 단일 배열 원소에 대한 논리 연산(Logical operations)을 위한 논리 함수

 

  (1-6-3-1) 배열 원소가 조건을 만족하지 않는 경우 참 반환 : np.logical_not(condition)

 

 

# logical_not : Compute the truth value of NOT x element-wise, equivalent to -x

 

In [23]: b = np.array([0, 1, 2, 3, 4])


In [24]: np.logical_not( b <= 2 )

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

 

 

 

2개 배열 간 함수인 Binary Universal Unfctions(Ufuncs) 소개는 http://rfriend.tistory.com/286 를 참고하시기 바랍니다.

 

많은 도움 되었기를 바랍니다.

 

 

 

Posted by R Friend R_Friend

이전 포스팅에서는
 
 - 범용함수(universal function, ufuncs)의 정의 및 유형
 
 
(1) 1개의 배열에 대한 ufuncs (Unary universal functions) 중에서
 
 - (1-1) 올림 및 내림 범용 함수 (rounding ufuncs)
 - (1-2) 합(sums), 곱(products), 차분(difference), 기울기(gradient) 범용함수
 - (1-3) 지수함수(exponential function), 로그함수 (logarithmic function)

 - (1-4) 삼각함수(trigonometric functions)

 

들에 대해서 알아보았습니다.

 

이번 포스팅에서는 Unary ufuncs 중에서 

 

 - (1-5) 수 처리 함수, 부호 판별 범용 함수들로서

 

수 처리 함수 : 절대값(absolute value), 제곱근(square root), 제곱값(square), 정수와 소수점 값(integral and fractional parts)

 

부호(sign) 판별 함수 : 1 (positive), 0(zero), -1(negative) 값 반환

 

등에 대해서 알아보겠습니다.

 

 

먼저, 수 처리 관련된 Unary funcs 입니다.  절대값, 제곱근, 제곱, 정수와 소수점 값 등 기본적인 것들로서 예제를 보면 금방 이해할 수 있기 때문에 추가적인 설명은 안 달겠습니다.

 

  (1-5-1) 배열 원소의 절대값 (absolute value) 범용 함수 : np.abs(x), np.fabs(x)

 

 

In [1]: import numpy as np


In [2]: x = np.array([-100, 1, -4, 100])


In [3]: x

Out[3]: array([-100, 1, -4, 100])

 

# abs, fabs : element-wise absolute value for integer, floating point, complex values

 

In [4]: np.abs(x)

Out[4]: array([100, 1, 4, 100])

 

In [5]: np.fabs(x)  # faster abs for non-complex-valued data

Out[5]: array([ 100., 1., 4., 100.])

 

 

 

 

  (1-5-2) 배열 원소의 제곱근(Square Root) 범용 함수 : np.sqrt(y)

 

 

In [6]: y = np.array([1, 4, 100])

 

# sqrt : Compute the square root of each element, equivalent to x**0.5

In [7]: np.sqrt(y)  # equivalent to x**0.5

Out[7]: array([ 1., 2., 10.])

 

In [8]: y**0.5

Out[8]: array([ 1., 2., 10.])

 

 

 

 

  (1-5-3) 배열 원소의 제곱값 (square value) 범용 함수 : np.square(y)

 

 

In [9]: y

Out[9]: array([ 1, 4, 100])

 

# square : Compute the square of each element, equivalent to x**2

In [10]: np.square(y) # equvalent to y**2

Out[10]: array([ 1, 16, 10000], dtype=int32)

 

In [11]: y**2

Out[11]: array([ 1, 16, 10000])

 

 

 

 

 (1-5-4) 배열 원소의 정수와 소수점을 구분하여 2개의 배열 반환 : np.modf(z)

 

np.modf() 범용함수는 1개의 배열을 input으로 받아서 특이하게도 2개의 배열을 output으로 반환합니다. 반환되는 첫번째 배열은 원래 배열의 각 원소들의 소수점 부분(fractional parts)으로 구성되어 있구요, 반환되는 두번째 배열에는 원래 배열의 각 원소들의 정수 부분(integral parts)으로 구성되어 있습니다.

 

만약 정수 부분으로만 구성된 두번째 배열을 선택하고 싶다면 np.modf(z)[1] 처럼 하면 됩니다.

 

 

In [12]: z = np.array([3.5, 7.8, -10.3])


In [13]: z

Out[13]: array([ 3.5, 7.8, -10.3])

 

# modf : return fractional and integral prats of array as separate array
# 1st array : fractional parts, 2nd array : integral parts

 

In [14]: np.modf(z)

Out[14]: (array([ 0.5, 0.8, -0.3]), array([ 3., 7., -10.]))

 

# indexing 2nd array of the returned array, which are integral parts 

In [15]: np.modf(z)[1]

Out[15]: array([ 3., 7., -10.])

 

In [16]: np.modf(z)[0]

Out[16]: array([ 0.5, 0.8, -0.3])

 

 

 

 

  (1-5-5) 배열 원소의 부호 판별 함수 : np.sign(x)  ☞ 1 (positive), 0(zero), -1(negative)

 

 

# sign : returns the sign of each element : 1 (positive), 0(zero), -1(negative)

 

In [17]: c = np.array([-2, -1, 0, 1, 2])


In [18]: c

Out[18]: array([-2, -1, 0, 1, 2])


In [19]: np.sign(c)

Out[19]: array([-1, -1, 0, 1, 1])

 

 

다음번 포스팅에서는 논리 함수 (logical unary ufuncs)에 대해서 알아보겠습니다.

 

많은 도움 되었기를 바랍니다.

 

Posted by R Friend R_Friend

이전 포스팅에서는

 

 - 범용함수(universal function, ufuncs)의 정의 및 유형

 

 

(1) 1개의 배열에 대한 ufuncs (Unary universal functions) 중에서

 

 - (1-1) 올림 및 내림 범용 함수 (rounding ufuncs)

 - (1-2) 합(sums), 곱(products), 차분(difference), gradient 범용함수

 - (1-3) 지수함수(exponential function), 로그함수 (logarithmic function)

 

에 대해서 소개하였습니다.

 

이번 포스팅에서는 Unary ufuncs 4번째로

 

 - (1-4) 삼각함수 (trigonometric functions)

 

에 대해서 알아보겠습니다.

 

 

고등학교 때 배웠던 삼각함수 공식을 복습하는 것으로 먼저 시작해보겠습니다. (이미 다 아는 이과생들은 pass... ^^;  긴가민가하는 문과생들은 복기... ^^;;;)

 

sine (줄여서 sin), cosine (줄여서 cos), tangent (줄여서 tan) 공식은 아래 밑변 AC, 높이 BC, 빗변 AB를 가지고 사이각이 (theta degree) 인 직각삼각형 ABC 를 가지고 삼각함수를 나타내본 것입니다.

 

 

 

[ 삼각함수 (Trigonometric Functions) ]

 

 

 

  

삼각함수는 어디에 쓰나 싶을 텐데요, 주기적인 파동형태를 띠는 함수 (예: 주파수, 물결 파동 등) 를 나타낼 때 sine function 을 사용합니다.  벡터 내적 계산할 때 cosine function 을 사용하기도 하구요. 고속 푸리에 변환 (FFT : Fast Fourier Transformation) 과 벡터 내적 계산 관련 자세한 내용은 아래 포스팅 링크 참고하세요.

 

 

 

참고로, degree는 우리가 일반적으로 사용하는 것처럼 원을 0~360도로 표기하는 방법이구요, radian은 부채꼴의 호의 길이와 반지름의 길이가 같게 되는 각도를 1 radian이라고 합니다. 

 

180 degree = π radian 이며,

1 degree = π radian/180 ,

1 radian = 180 degree/ π = 57.3 의 관계가 있습니다. (슬슬 헷갈리기 시작하죠? -_-?)

 

 

Python NumPy의 삼각함수는 radian을 사용하기 때문에 degree 를 radian으로 바꿔주기 위해서 degree * np.py/180 을 해주었습니다. ( np.deg2rad(x) 함수를 사용해도 됨 )

 

 

 

  (1-4-1) 삼각함수 (trigonometric functions) : np.sin(), np.cos(), np.tan()

 

In [1]: import numpy as np


In [2]: np.sin(np.array((0., 30., 45., 60., 90.))*np.pi / 180.)

Out[2]: array([ 0.        ,  0.5       ,  0.70710678,  0.8660254 ,  1.        ])


In [3]: np.cos(np.array((0., 30., 45., 60., 90.))*np.pi / 180.)

Out[3]:

array([  1.00000000e+00,   8.66025404e-01,   7.07106781e-01,
          5.00000000e-01,   6.12323400e-17])


In [4]: np.tan(np.array((0., 30., 45., 60., 90.))*np.pi / 180.)

Out[4]:

array([  0.00000000e+00,   5.77350269e-01,   1.00000000e+00,
          1.73205081e+00,   1.63312394e+16])

 

 

 

 

 

참고로, 아래는 주요 Degree 혹은 radian 별  삼각함수 값 (Special values in trigonometric functions) 들입니다.

 

* 출처 : Wikipedia (https://en.wikipedia.org/wiki/Trigonometric_functions)

 

 

 

 

  (1-4-2) 싸인 곡선 그리기 (plotting sine curve)

 

 

In [5]: import matplotlib.pyplot as plt


In [6]: x = np.arange(0, 2*np.pi, 0.1)


In [7]: y = np.sin(x)


In [8]: plt.plot(x, y)

Out[8]: [<matplotlib.lines.Line2D at 0x94295f8>]

 


In [9]: plt.show()

 

 

 

 

 

주기적으로 회전 운동(a circular movement)을 하는 단자를 시간의 흐름(x축)에 따른 높낮이 변화(y축)를 시계열 그래프로 나타내면 그게 바로 위의 사인 곡선(sine curve)이 됩니다. 저 주기를 가지고 주파수를 계산할 때 FFT (Fast Fourier Transformation)을 사용하구요.

 

 

 

 

 

 

 

  (1-4-3) 삼각함수의 역수

 

삼각함수의 역수cosecant (줄여서 csc), secant (줄여서 sec), cotangent (줄여서 cot) 함수는 아래와 같이 정의합니다.

 

 

 



 

 

 

 

 

 

  (1-4-4) 역삼각함수 : np.arcsin(), np.arccos(), np.arctan

 

 

In [10]: np.arcsin(1) # pi/2

Out[10]: 1.5707963267948966

 

In [11]: np.sin(1.5707963267948966)

Out[11]: 1.0

 

In [12]: np.sin(np.arcsin(1))

Out[12]: 1.0

 


 

In [13]: np.arcsin([-1, 0, 1]) # real part lies in [-pi/2, pi/2]

Out[13]: array([-1.57079633,  0.        ,  1.57079633])


In [14]: np.arccos([-1, 0, 1]) # real part lies in [0, pi]

Out[14]: array([ 3.14159265,  1.57079633,  0.        ])


In [15]: np.arctan([-1, 0, 1]) # real part lies in [-pi/2, pi/2]

Out[15]: array([-0.78539816,  0.        ,  0.78539816])

 

 

 

 

 

  (1-4-5) degree를 radian으로 변환 : np.deg2rad(x)

            radian을 degree로 변환 : np.rad2deg(x)

 

 

degree를 radian으로 바꾸고 싶을 때는 np.deg2rad(x) 함수를 사용하면 되구요,

radian을 degree로 바꾸고 싶을 때는 np.rad2deg(x) 함수를 사용하면 됩니다.

 

 

# Convert angles from degrees to radians : np.deg2rad
# deg2rad(x) is x * pi / 180

 

In [16]: np.deg2rad(180)

Out[16]: 3.1415926535897931

 

 

# Convert angles from radians to degrees : np.rad2deg
# rad2deg(x) is 180 * x / pi

In [17]: np.rad2deg(np.pi)

Out[17]: 180.0

 

 

 

 

많은 도움 되었기를 바랍니다. 

 

 

Posted by R Friend R_Friend

이전 포스팅에서는

 

 - 범용함수(universal function, ufuncs)의 정의 및 유형

 

 

(1) 1개의 배열에 대한 ufuncs (Unary universal functions) 중에서

 

 - (1-1) 올림 및 내림 범용 함수 (rounding ufuncs)

 - (1-2) 합(sums), 곱(products), 차분(difference), 기울기(gradient) 범용함수

 

들에 대해서 알아보았습니다.

 

이번 포스팅에서는 Unary ufuncs 중에서

 

 - (1-3) 지수함수(exponential function), 로그함수 (logarithmic function)

 

에 대해서 알아보겠습니다.

 

 

고등학교 때 지수함수, 로그함수에 대해서 배웠을 텐데요, 기억이 가물가물 하신분들을 위해서 간단히 지수함수, 로그함수에 대해서 먼저 복기를 해본 후에 Python NumPy 의 지수함수, 로그함수 사용법으로 넘어가겠습니다.

 

 

지수함수(exponential function)는 아래 왼쪽의 그래프처럼 인 형태의 함수를 말합니다.  아래 [그림1] 왼쪽의 지수함수 예시 그래프는   지수함수의 그래프로서, (x=0, y=1), (x=1, y=2) 지점을 지나고 있습니다.

 

로그함수(logarithmic function)는 지수함수의 역함수(inverse function) 입니다. 즉, 아래 [그림1] 그래프의 예를 들자면원래 지수함수였던 의 역함수는  함수인데요, 이를 표기하기 편하도록 라고 하자고 약속을 한 것입니다. (밑이 '2'인 로그함수)

 

 

[그림1] 지수함수와 로그함수의 관계 및 그래프 예시

 

 

 

 

특히, 자연상수 e 를 밑으로 하는 로그함수를 자연로그(natural logarithm) 하며, 처럼 쓰기 보다는 보통 자연상수 e를 생략하고 그냥 혹은 로 쓰곤 합니다. 아래 [그림2] 그래프를 참고하세요.

 

(참고로, 자연상수 e2.71828182846... 의 값을 가지는 무리수이며, 수학자의 이름을 따서 '오일러의 수(Euler's number)' 또는 '네이피어의 수(Napier's number)'라고도 함)

 

 

[그림2] 밑(base)이 자연상수 e 인 지수함수와 자연로그 함수 그래프

 

 

 

 

간단한 복기는 여기까지 하고요, 이제 Python NumPy의 지수함수, 로그함수에 대해 알아보겠습니다.

별것 없구요, 간단합니다. ^^'

 

  (1-3-1) 지수함수 (exponential function) : np.exp()

 

NumPy의 np.exp() 함수는 밑(base)이 자연상수 e 인 지수함수  로 변환해줍니다.

 

 

In [1]: import numpy as np


In [2]: x = np.array([0.00001, 1, 2, 4, 10, 100])


In [3]: x

Out[3]:

array([  1.00000000e-05,   1.00000000e+00,   2.00000000e+00,
          4.00000000e+00,   1.00000000e+01,   1.00000000e+02])


In [4]: np.exp(x)

Out[4]:

array([  1.00001000e+00,   2.71828183e+00,   7.38905610e+00,
          5.45981500e+01,   2.20264658e+04,   2.68811714e+43])

 

 

 

 

 (1-3-2) 로그함수 (logarithmic function) : np.log(x), np.log10(x), np.log2(x), log1p(z) 

 

지수함수의 역함수인 로그함수는 밑이 자연상수 e, 혹은 10, 또는 2 이냐에 따라서 np.log(x), np.log10(x), np.log2(x) 를 구분해서 사용합니다.

 

 

# natural logarithm (base e)

 

In [5]: np.log(x)

Out[5]:

array([-11.51292546,   0.        ,   0.69314718,   1.38629436,
           2.30258509,   4.60517019])

 

 

# log base 10

In [6]: np.log10(x)

Out[6]: array([-5.        ,  0.        ,  0.30103   ,  0.60205999,  1.        ,  2.        ])

 

 

# log base 2

In [7]: np.log2(x)

Out[7]:

array([-16.60964047,   0.        ,   1.        ,   2.        ,
           3.32192809,   6.64385619])

 

 

 

 

로그함수의 경우 위의 [그림2]의 하단에 있는 자연로그 함수 그래프를 보면 알겠지만, x=0 인 경우 y가 -무한대(-infinite)의 값을 가집니다.  아래의 Out[9]번에 보면 NumPy 에 '0'이 포함된 배열을 np.log() 함수에 대입하면 'RuntimeWarning: divide by zero encountered in log' 라는 경고메시지가 뜨고, -inf 가 포함된 배열을 반환하게 됩니다. 이럴 때 사용하는 방법이 'x+1'을 해줘서 '0' -> '1' 로 바꿔주는 겁니다. np.log1p() 함수가 바로 이 역할을 해주는 함수입니다. 그러면 y값이 '-inf' -> '0'으로 바뀌게 되죠.

 

 

In [8]: z = np.array([0, 1.71828])


In [9]: np.log(z)

C:\Anaconda3\lib\site-packages\spyderlib\widgets\externalshell\start_ipython_kernel.py:1: RuntimeWarning: divide by zero encountered in log

# -*- coding: utf-8 -*-

Out[9]: array([ -inf, 0.54132379])

 

 

# log(1+z) = np.log1p(z)

In [10]: np.log1p(z)

Out[10]: array([ 0. , 0.99999933])

 

 

 

 

물론 np.log1p() 함수를 안쓰고 그냥 np.log() 함수를 써서 아래처럼 np.log(1+z) 라고 해도 똑같은 결과를 얻을 수 있습니다.

 

 

In [11]: np.log(1+z)

Out[11]: array([ 0. , 0.99999933])

 

 

 

 

그럼, 지수함수, 로그함수는 어디에 써먹는 건가 궁금할 것 같습니다.

한가지 예를 들자면 오른쪽으로 심하게 skewed된 멱함수(power law function) 분포를 띠는 데이터를 정규분포(normal distribution) 로 변환할 때 로그 변환 (log transformation)을 사용하곤 합니다.

 

자세한 내용은 오른쪽 포스팅 참고하세요.  ☞  http://rfriend.tistory.com/53

 

 

여기서 끝내기 조금 아쉬우니 지수함수와 로그함수의 성질(properties of exponential and logarithmic function)도 복기해보겠습니다. 논문 읽다보면 지수함수와 로그함수의 성질을 알아야지 이해가 되는 공식 전개가 가끔씩 나오니 기억해두면 좋겠지요?!  증명은 생략합니다. ^^'

 

 

 

다음번 포스팅에서는 Unary ufuncs 의 네번째로 삼각함수(trigonometric functions)를 알아보겠습니다.

 

많은 도움 되었기를 바랍니다.

 

 

Posted by R Friend R_Friend

지난번 포스팅에서는 NumPy 에서 제공하는

 

 - (1) 단일 배열 대상의 범용 함수

       (Unary Universal Functions)

 - (2) 2개 배열 대상의 범용 함수

       (Binary Universal Functions)

 

에 대해서 간략히 소개를 하였습니다.

 

그리고 단일 배열 대상의 범용 함수 중에서 (1-1) '올림 혹은 내림 (Rounding)' 함수들(np.around, np.round_, np.rint, np.fix, np.ceil, np.floor, np.trunc)에 대해서 알아보았습니다.

 

이번 포스팅에서는 단일 배열 대상의 범용 함수(Unary ufuncs) 중에서 (1-2) 배열 원소 간 곱(products), 합(sums), 차분(differences) 범용 함수들에 대해서 알아보겠습니다.  (함수가 많아서 한꺼번에 포스팅하기에 버거우므로 여러번 나누어서 포스팅합니다)

 

 

[ Unary ufuncs : 배열 원소 간 곱 (products), 합 (sums), 차분 (differences) ]

 

 

 

 (1-2) 배열 원소 간 곱(products), 합(sums), 차분(differences), 기울기(gradient) 범용함수

 

1차원 배열 b와 2차원 배열 c를 가지고 예를 들어 설명하겠습니다.

 

 In [1]: import numpy as np


In [2]: b = np.array([1, 2, 3, 4]) # 1 dimension


In [3]: b

Out[3]: array([1, 2, 3, 4])


In [4]: c = np.array([[1, 2], [3, 4]]) # 2 dimension


In [5]: c

Out[5]:

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

 

 

 

 

 (1-2-1) 배열 원소 간 곱 범용 함수 (products universal funcstions) : np.prod()

 

2차원 배열의 경우 axis=0 이면 같은 열(column)위*아래 방향으로 배열 원소 간 곱하며, axis=1 이면 같은 행(row)의 왼쪽*오른쪽 원소 간 곱을 합니다.

 

 

# (1-2-1) np.prod() : Return the product of array elements over a given axis

 

# 1 dimensional array

In [3]: b

Out[3]: array([1, 2, 3, 4])

 

In [6]: np.prod(b)  # 1*2*3*4

Out[6]: 24

 

# 2 dimensional array

In [5]: c

Out[5]:

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

 

In [7]: np.prod(c, axis=0# [1*3, 2*4]  ↓

Out[7]: array([3, 8])


In [8]: np.prod(c, axis=1# [1*2, 3*4]  →

Out[8]: array([ 2, 12])

 

 

 

 

 (1-2-2) 배열 원소 간 합치기 범용 함수 (sum universal functions) : np.sum()

 

keepdims=True 옵션을 설정하면 1 차원 배열로 배열 원소 간 합을 반환합니다.

 

 

# (1-2-2) np.sum() : Sum of array elements over a given axis

 

# 1 dimensional array

In [3]: b

Out[3]: array([1, 2, 3, 4])

 

In [9]: np.sum(b) # [1+2+3+4]

Out[9]: 10

 

# the axes which are reduced are left in the result as dimensions with size one

In [10]: np.sum(b, keepdims=True)

Out[10]: array([10])  # 1 dimension array

 

In [11]: np.sum(b, keepdims=True).shape  # 1 dimension array

Out[11]: (1,)

 

 

 

2차원 배열의 경우 axis=0 을 설정하면 같은 열(column)의 위+아래 원소 값을 더하며, axis=1 을 설정하면 같은 행(row)의 왼쪽+오른쪽 원소 값을 더하여 1차원 배열을 반환합니다.

 

 

# 2 dimensional array

In [5]: c

Out[5]:

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

 

In [12]: np.sum(c, axis=0)  # [1+3, 2+4]  ↓

Out[12]: array([4, 6])


In [13]: np.sum(c, axis=1)  # [1+2, 3+4]  →

Out[13]: array([3, 7])

 

 

 

 

 (1-2-3) NaN 이 포함된 배열 원소 간 곱하기 범용 함수 : np.nanprod()

 

np.nanprod() 함수는 NaN (Not a Numbers) 을 '1'(one)로 간주하고 배열 원소 간 곱을 합니다.

 

 

# (1-2-3) np.nanprod() : Return the product of array elements

#                             over a given axis treating Not a Numbers (NaNs) as ones

 

In [14]: d = np.array([[1, 2], [3, np.nan]])


In [15]: d

Out[15]:

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


In [16]: np.nanprod(d, axis=0)  # [1*3, 2*1]  ↓

Out[16]: array([ 3., 2.])


In [17]: np.nanprod(d, axis=1)  # [1*2, 3*1]  →

Out[17]: array([ 2., 3.])

 

 

 

 

 (1-2-4) NaN이 포함된 배열 원소 간 더하기 범용 함수 : np.nansum()

 

np.nansum() 함수는 NaN (Not a Numbers)을 '0'(zero)으로 간주하고 배열 원소 간 더하기를 합니다.

 

 

In [15]: d

Out[15]:

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

 

# (1-2-4) np.nansum() : Return the sum of array elements

#                             over a given axis treating Not a Numbers (NaNs) as zero

 

In [18]: np.nansum(d, axis=0)  # [1+3, 2+0]  ↓

Out[18]: array([ 4., 2.])


In [19]: np.nansum(d, axis=1)  # [1+2, 3+0]  →

Out[19]: array([ 3., 3.])

 

 

 

 

 (1-2-5) 배열 원소 간 누적 곱하기 범용 함수 : np.cumprod()

 

axis=0 이면 같은 행(column)의 위에서 아래 방향으로 배열 원소들을 누적(cumulative)으로 곱해 나가며, axis=1 이면 같은 열(row)에 있는 배열 원소 간에 왼쪽에서 오른쪽 방향으로 누적으로 곱해 나갑니다.

 

 

In [20]: e = np.array([1, 2, 3, 4])


In [21]: e

Out[21]: array([1, 2, 3, 4])


In [22]: f = np.array([[1, 2, 3], [4, 5, 6]])


In [23]: f

Out[23]:

array([[1, 2, 3],
        [4, 5, 6]])

 

 

# (1-2-5) np.cumprod() : Return the cumulative product of elements along a given axis

In [24]: np.cumprod(e)  # [1, 1*2, 1*2*3, 1*2*3*4]

Out[24]: array([ 1, 2, 6, 24], dtype=int32)


In [25]: np.cumprod(f, axis=0)  # [[1, 2, 3], [1*4, 2*5, 3*6]]  ↓

Out[25]:

array([[ 1,  2,  3],
        [ 4, 10, 18]], dtype=int32)


In [26]: np.cumprod(f, axis=1)  # [[1, 1*2, 1*2*3], [4, 4*5, 4*5*6]]  →

Out[26]:

array([[  1,   2,   6],
        [  4,  20, 120]], dtype=int32)

 

 

 

 

 (1-2-6) 배열 원소 간 누적 합 구하기 범용 함수 : np.cumsum()

 

axis=0 이면 같은 행(column)의 위에서 아래 방향으로 배열 원소들을 누적(cumulative)으로 합해 나가며, axis=1 이면 같은 열(row)에 있는 배열 원소 간에 왼쪽에서 오른쪽 방향으로 누적으로 합해 나갑니다.

 

 

In [21]: e

Out[21]: array([1, 2, 3, 4])

 

# (1-2-6) np.cumsum(a, axis) : Return the cumulative sum of the elements along a given axis

 

In [27]: np.cumsum(e)  # [1, 1+2, 1+2+3, 1+2+3+4]

Out[27]: array([ 1,  3,  6, 10], dtype=int32)

 

 

In [23]: f

Out[23]:

array([[1, 2, 3],
        [4, 5, 6]])

 

In [28]: np.cumsum(f, axis=0)  # [[1, 2, 3], [1+4, 2+5, 3+6]]  ↓

Out[28]:

array([[1, 2, 3],
        [5, 7, 9]], dtype=int32)


In [29]: np.cumsum(f, axis=1)  # [[1, 1+2, 1+2+3], [4, 4+5, 4+5+6]]  →

Out[29]:

array([[ 1,  3,  6],
        [ 4,  9, 15]], dtype=int32)

 

 

 

 

  (1-2-7) 배열 원소 간 n차 차분 구하기 : np.diff()

 

 

# (1-2-7) diff(a, n, axis) : Calculate the n-th discrete difference along given axis

 

In [30]: g = np.array([1, 2, 4, 10, 13, 20])


In [31]: g

Out[31]: array([ 1, 2, 4, 10, 13, 20])

 

 

# 1차 차분 (1st order differencing)

In [32]: np.diff(g)  # [2-1, 4-2, 10-4, 13-10, 20-13]

Out[32]: array([1, 2, 6, 3, 7])

 

 

# 2차 차분 (2nd order differencing) => 1차 차분 결과 Out[32] 를 가지고 한번 더 차분

In [33]: np.diff(g, n=2)  # [2-1, 6-2, 3-6, 7-3]  <- using Out[32] array (1st order difference)

Out[33]: array([ 1, 4, -3, 4])

 

 

# 3차 차분 (3rd order differencing) => 2차 차분 결과 Out[33] 을 가지고 한번 더 차분

In [34]: np.diff(g, n=3)  # [4-1, -3-4, 4-(-3)]  <- using Out[33] array (2nd order diffenence)

Out[34]: array([ 3, -7, 7])

 

 

 

2차원 배열의 경우 axis=0 이면 같은 열(column)의 아래에서 위 방향으로 차분(difference)을 하며,

axis=1 이면 같은 행(row)의 오른쪽에서 왼쪽 방향으로 차분을 합니다.

 

 

#---- 2 dimentional arrays

 

In [35]: h = np.array([[1, 2, 4, 8], [10, 13, 20, 15]])


In [36]: h

Out[36]:

array([[ 1,  2,  4,  8],
        [10, 13, 20, 15]])

 

In [37]: np.diff(h, axis=0)  # [10-1, 13-2, 20-4, 15-8] ↑

Out[37]: array([[ 9, 11, 16, 7]])


In [38]: np.diff(h, axis=1)  # [[2-1, 4-2, 8-4], [13-10, 20-13, 15-20]] ←

Out[38]:

array([[ 1,  2,  4],
        [ 3,  7, -5]])

 

 

# n=2 이면 1차 차분 결과인 Out[38] 배열에 대해 한번 더 차분

 

In [39]: np.diff(h, n=2, axis=1)  [[2-1, 4-2], [7-3, -5-7]] ←

Out[39]:

array([[  1,   2],
        [  4, -12]])

 

 

 

 

 (1-2-8) 차분 결과를 1차원 배열(1 dimensional array)로 반환해주는 함수 : ediff1d()

 

2차원 배열에 대한 차분인 np.diff(h, axis=1) 의 경우 Out[38] 처럼 2차원 배열을 반환합니다. 반면에 ediff1d(h) 함수를 사용하면 Out[41] 처럼 차분 결과를 1차원 배열로 반환합니다.

 

 

# (1-2-8) ediff1d(ary[, to_end, to_begin])

#           : The differences between consecutive elements of an array

 

In [31]: g

Out[31]: array([ 1, 2, 4, 10, 13, 20])

 

In [40]: np.ediff1d(g)

Out[40]: array([1, 2, 6, 3, 7])

 

 

# 2 dimensional array

 

In [36]: h

Out[36]:

array([[ 1,  2,  4,  8],
        [10, 13, 20, 15]])

 

# The returned array is always 1D

In [41]: np.ediff1d(h)

Out[41]: array([ 1, 2, 4, 2, 3, 7, -5])  # 1D array, not 2D array

 

 

 

np.ediff1d() 함수의 시작부분과 끝 부분의 값을 to_begin, to_end 로 설정해줄 수도 있습니다.

 

 

In [42]: np.ediff1d(h, to_begin=np.array([-100, -99]), to_end=np.array([99, 100]))

Out[42]: array([-100, -99, 1, 2, 4, 2, 3, 7, -5, 99, 100])

 

 

 

 

  (1-2-9) 기울기(gradient) 구하기 범용 함수 : np.gradient()

 

gradient는 1차 편미분한 값들로 구성된 배열입니다. 아래 예제에 np.gradient() 함수가 어떻게 계산되는지를 수식을 적어놓았으니 참고하시기 바랍니다.  말로 설명하기가 쉽지가 않네요. ^^; 

 

 

In [31]: g

Out[31]: array([ 1, 2, 4, 10, 13, 20])

 

 

# [(2-1), {(2-1)+(4-2)}/2, {(4-2)+(10-4)}/2, {(10-4)+(13-10)}/2, {(13-10)+(20-13)}/2, (20-13)]

In [43]: np.gradient(g)

Out[43]: array([ 1. , 1.5, 4. , 4.5, 5. , 7. ])

 


# N scalars specifying the sample distances for each dimension

# x축 1단위가 '2'이므로 양쪽 옆으로 x축 변화에 따른 y값 변화를 보는 것이므로 2(단위)*2(방향)으로 나누어 줌

# [(2-1)/2, {(2-1)+(4-2)}/2*2, {(4-2)+(10-4)}/2*2, {(10-4)+(13-10)}/2*2, {(13-10)+(20-13)}/2*2, (20-13)/2] 

In [44]: np.gradient(g, 2)

Out[44]: array([ 0.5 , 0.75, 2. , 2.25, 2.5 , 3.5 ])

 


# Gradient is calculated using N-th order accurate differences at the boundaries

# 양 옆에만 2차 차분 : 1 - (1.5 -1) = 0.5,   7 + (7-5) = 9

In [45]: np.gradient(g, edge_order=2)

Out[45]: array([ 0.5, 1.5, 4. , 4.5, 5. , 9. ])

 

 

 

아래는 2차원 배열에 대한 gradient 구하는 예제입니다. np.gradient(h, axis=0)과 np.gradient(h, axis=1)을 짬뽕해 놓은 것이 np.gradient(h) 라고 보면 되겠습니다.  gradient 방법은 위의 1차원에서 소개한 방법과 같습니다.

 

 

# 2 dimensional array

 

In [36]: h

Out[36]:

array([[ 1,  2,  4,  8],
        [10, 13, 20, 15]])

 

 

# the first array stands for the gradient in rows and the second one in columns direction

In [46]: np.gradient(h)

Out[46]:

[array([[  9.,  11.,  16.,   7.],
         [  9.,  11.,  16.,   7.]]),

 array([[ 1. ,  1.5,  3. ,  4. ],
         [ 3. ,  5. ,  1. , -5. ]])]

 


# The axis keyword can be used to specify a subset of axes of which the gradient is calculated

 

In [47]: np.gradient(h, axis=0)  # ↑

Out[47]:

array([[  9.,  11.,  16.,   7.],
        [  9.,  11.,  16.,   7.]])


In [48]: np.gradient(h, axis=1)  # ←

Out[48]:

array([[ 1. ,  1.5,  3. ,  4. ],
        [ 3. ,  5. ,  1. , -5. ]])

 

 

 

다음번 포스팅에서는 지수함수, 로그함수, 삼각함수에 대해서 다루어보겠습니다.

 

많은 도움 되었기를 바랍니다.

 

 

Posted by R Friend R_Friend

이번 포스팅부터는 몇 번에 나누어서 로그함수, 삼각함수, 사칙연산 함수 등과 같이 일반적으로 많이 사용되는 범용 함수 (universal functions)들에 대해서 소개하겠습니다.

 

Python에서 범용 함수를 지원하는 모듈이 여러개 있습니다. 

 

Pytho 배울 때 초반에 배우는 math module은 실수(real number)에 대해서만 범용함수를 지원하며, cmath module 은 복소수(complex number) 까지 범용함수를 지원합니다. numpy module은 실수, 복소수, 복소수 행렬 (complex matrix)의 원소 간 범용 함수를 모두 지원하므로 사용 범위가 가장 넓어 매우 유용합니다.  배열의 원소간 연산을 위해 NumPy의 Ufunc 함수는 쓸모가 많습니다. NumPy는 맥가이버 칼 같다고나 할까요.

 

[ Python modules for Universal Functions ]

 

 

 

 

NumPy 범용 함수는 몇 개의 배열에 대해 적용이 되는지에 따라서

 - (1) 1개의 배열에 적용하는 Unary Universal Functions (ufuncs)

 - (2) 2개의 배열에 대해 적용하는 Binary Universal Functions (ufuncs)

으로 구분할 수 있습니다.

 

범용함수 종류가 너무 많아서 포스팅에 한꺼번에 소개하기가 버거우므로, 서너번에 나누어서 Unary Universal Functions를 먼저 소개하고, 다음으로 Binary Ufuncs  순서로 알아보겠습니다.

 

 

 

 

  (1-1) 올림 혹은 내림 범용 함수 (round universal functions)

 

비슷비슷한 함수들이 여러개 있는데요, 말로 설명하는 것보다 예를 자세히 살펴보고 비교해보는 것이 이해하기에 쉽고 빠를 것 같습니다.

 

 

# import module and making an array

In [1]: import numpy as np


In [2]: a = np.array([-4.62, -2.19, 0, 1.57, 3.40, 4.06])


In [3]: a

Out[3]: array([-4.62, -2.19, 0. , 1.57, 3.4 , 4.06])

 

 

 

 (1-1-1) np.around(a) : 0.5를 기준으로 올림 혹은 내림

 

 

# np.around(a) : Evenly round to the given number of decimals

 

In [3]: a

Out[3]: array([-4.62, -2.19, 0. , 1.57, 3.4 , 4.06])

 

In [4]: np.around(a)

Out[4]: array([-5., -2., 0., 2., 3., 4.]) 

 

 

 

 

 (1-1-2) np.round_(a, N) : N 소수점 자릿수까지 반올림

 

  

# np.round_(a, n) : Round an array to the given number of decimals

 

In [3]: a

Out[3]: array([-4.62, -2.19, 0. , 1.57, 3.4 , 4.06])

 

In [5]: np.round_(a, 1)

Out[5]: array([-4.6, -2.2, 0. , 1.6, 3.4, 4.1]) 

 

 

 

 

 (1-1-3) np.rint(a) : 가장 가까운 정수로 올림 혹은 내림

 

 

# round elements to the nearest integer

 

In [3]: a

Out[3]: array([-4.62, -2.19, 0. , 1.57, 3.4 , 4.06])

 

In [6]: np.rint(a)

Out[6]: array([-5., -2., 0., 2., 3., 4.])

 

 

 

 

 (1-1-4) np.fix(a) : '0' 방향으로 가장 가까운 정수로 올림 혹은 내림

 

 

# Round to nearest integer towards zero

 

In [3]: a

Out[3]: array([-4.62, -2.19, 0. , 1.57, 3.4 , 4.06])

 

In [7]: np.fix(a)

Out[7]: array([-4., -2., 0., 1., 3., 4.])

 

 

 

 

 (1-1-5) np.ceil(a) : 각 원소 값보다 크거나 같은 가장 작은 정수 값 (천장 값)으로 올림

 

 

# the smallest integer greater than or equal to each element 

 

In [3]: a

Out[3]: array([-4.62, -2.19, 0. , 1.57, 3.4 , 4.06])

 

In [8]: np.ceil(a)

Out[8]: array([-4., -2., 0., 2., 4., 5.])

 

 

 

 

 (1-1-6) np.floor(a) : 각 원소 값보다 작거나 같은 가장 큰 정수 값 (바닥 값)으로 내림

 

 

# the largest integer less than or equal to each element

 

In [3]: a

Out[3]: array([-4.62, -2.19, 0. , 1.57, 3.4 , 4.06])

 

In [9]: np.floor(a)

Out[9]: array([-5., -3., 0., 1., 3., 4.])

 

 

 

 

 (1-1-7) np.trunc(a) : 각 원소의 소수점 부분은 잘라버리고 정수값만 남김

 

 

# Return the truncated value of the input, element-wise

 

In [3]: a

Out[3]: array([-4.62, -2.19, 0. , 1.57, 3.4 , 4.06])

 

In [10]: np.trunc(a)

Out[10]: array([-4., -2., 0., 1., 3., 4.])

 

 

 

다음번 포스팅에서는 단일 배열 범용 함수의 두번째 순서로 합(sums), 곱(products), 차분(difference), 미분(gradient) 함수에 대해서 알아보도록 하겠습니다.

 

많은 도움 되었기를 바랍니다.

 

 

Posted by R Friend R_Friend