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