최근에 python study를 하면서 정리도 할겸 포스팅을 하기로 했다. 잊지 않으려면, 나중에 찾아보려면 이렇게 기록으로 남기는것이 최선일 것이다.

1. Basic Indexing and Slicing

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

In [52]: arr

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

In [53]: arr[5]

Out[53]: 5

In [54]: arr[5:8]

Out[54]: array([5, 6, 7])

In [55]: arr[5:8] = 12

In [56]: arr

Out[56]: array([ 0, 1, 2, 3, 4, 12, 12, 12, 8, 9])


 python에서 slicing을 할 경우 마지막 index는 수학 표현으로 치면 개구간이다. In[54]의 결과를 보면 8은 결과에 포함되어 있지 않음을 알 수 있다. 

다음은 Numpy에서 array를 call by reference로 처리하고 있다는 것을 보여주는 예제이다.

In [57]: arr_slice = arr[5:8]

In [58]: arr_slice[1] = 12345

In [59]: arr

Out[59]: array([ 0, 1, 2, 3, 4, 12, 12345, 12, 8, 9])

 혹여 이런식으로 'view'를 생성해서 원래 값과의 연결됨을 원치 않는다면 arr_slice = arr[5:8].copy() 명령어를 사용하면 된다.

2. Expressing Conditional Logic as Array Operations

numpy.where function은 어떤 조건에 따라 x 혹은 y를 경우게 맞게 빠르게 보여주는 기능을 제공한다. Python에 기본적으로 탑재되어 있는 기능을 사용하면 다음과 같이 구현해야 한다.

In [143]: result = [(x if c else y)

.....: for x, y, c in zip(xarr, yarr, cond)]

In [144]: result

Out[144]: [1.1000000000000001, 2.2000000000000002, 1.3, 1.3999999999999999, 2.5]

 이 방법은 large array에 대해서 빠르지 않을 뿐더러 multidimensional arrays에 적합하지 않다. numpy.where 함수를 쓰면 다음과 같이 구현 가능하다.

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

In [146]: result

Out[146]: array([ 1.1, 2.2, 1.3, 1.4, 2.5])

numpy.where는 반드시 array를 필요로 하지 않는다.

In [147]: arr = randn(4, 4)

In [148]: arr

Out[148]:

array([[ 0.6372, 2.2043, 1.7904, 0.0752],

[-1.5926, -1.1536, 0.4413, 0.3483],

[-0.1798, 0.3299, 0.7827, -0.7585],

[ 0.5857, 0.1619, 1.3583, -1.3865]])

In [149]: np.where(arr > 0, 2, -2)

Out[149]:

array([[ 2, 2, 2, 2],

    [-2, -2, 2, 2],

    [-2, 2, 2, -2],

    [ 2, 2, 2, -2]])

이런식으로 where에 자유롭게 input을 입력하여 사용할 수 있다.

3. Mathematical and Statistical Methods

Numpy에서는 sum, mean, std 같은 수학적 연산 함수를 제공한다. 

In [151]: arr = np.random.randn(5, 4) # normally-distributed data

In [152]: arr.mean()

Out[152]: 0.062814911084854597

In [153]: np.mean(arr)

Out[153]: 0.062814911084854597

In [154]: arr.sum()

Out[154]: 1.2562982216970919

mean(), sum()과 같이 method에 인수를 지정하지 않으면 대상 array에 모든 값을 대상으로 수학연산을 행한다. 그런데 method에 인수로 정수값을 할당하면 'axis'를 따라 연산을 행한다. 예를들면 다음과 같다.

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

In [158]: arr.cumsum(0)                 In [159]: arr.cumprod(1)

Out[158]:                                     Out[159]:

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

   [ 3, 5, 7],                                     [ 3, 12, 60],

   [ 9, 12, 15]])                                [ 6, 42, 336]])

cumsumcumprod는 이름에서 알 수 있듯이 누적해서 합, 곱을 해주는 method이다. 여기서 좀 헷갈렸던 점이 'axis'를 따라 연산을 한다는 점이었다. 보통 2d-array를 취급할 때 앞에 오는 숫자가 대부분 행, 뒤 숫자가 열을 의미하기에 결과를 보기 전에 cumsum(0)을 입력하면 [0,1,3],[3,7,12] 이런식으로 출력이 될거라고 예상했었다. 그런데 'axis'를 따라서 연산한다는 의미를 잘 생각해보면 x축, y축 처럼 그 축위를 움직이면서 그 위치에 해당하는 값들에 대해 연산해 준다는 것이었다. 설명은 명확히 쓰여 있었으나 그 동안 해오던 것과 달라서 헷갈렸던 부분이었다.

+ Recent posts