NumPy에서 indexing은 4가지 방식을 따름.
- scalar를 이용한 indexing ( simple indexing ) :
array[0]
- slicing
- boolean mask :
array[array > 1]
- fancy indexing : vectorized indexing. index들을 element로 가지는 array를 넘겨줌.
- combined indexing : 앞서 4가지가 조합된 indexing
Fancy Indexing
image(or matrix)등에서 높이 (row, height), 넓이 (column, width)에 대해,
- 접근하고자하는 pixel (or entry)들의 index를
- square bracket안에 넘겨주는 방식임.
주의할 점은 fancy indexing으로 넘겨지는 array의 shape와 "같은 shape의 결과 array가 반환"됨.
간단하게 1차원에서 확인한다면 다음과 같음.
import numpy as np
x = np.array([0,1,2,3,4,5,6,7,8])
Fancy indexing은 다음과 같이 index로 구성된 array를 index위치에 넘겨줌.
fidx = [3, 7, 1]
x[fidx] # array([3, 7, 1])
Fancy indexing의 특징 중 하나는 넘겨준 fancy indexing의 shape에 맞추서 결과 ndarray가 만들어진다.
fidx =[[3, 7],
[4, 2]]
fidx = np.array(fidx)
x[fidx] # array([[3,7],[4,2]])
fidx
가 $2\times 2$ matrix이므로x[fidx]
도 $2\times 2$ matrix가 됨.
Fancy indexing에서 각 axis에 대한 index를 따로 지정하는 경우도 매우 많음.
x = x.reshape((3,3))
ridx = np.array([0,1,2])
cidx = np.array([2,0,1])
x[ridx,cidx] # array([2, 3, 7])
강력한 점은 broadcasting rule을 통해 해당 index들의 array들이 최종 index들의 ndarray가 된다는 점임.
x[ ridx[:,np.newaxis], cidx]
결과는 다음과 같음.
array([[2, 0, 1],
[5, 3, 4],
[8, 6, 7]])
ridx
가 $3 \times 1$ 이므로cidx
와 broadcasting이 이루어져 최종 idx는 다음과 같음.
$$\begin{bmatrix} \text{(0,2)} & \text{(0,0)} & \text{(0,1)} \\ \text{(1,2)} & \text{(1,0)} & \text{(1,1)} \\ \text{(2,2)} & \text{(2,0)} & \text{(2,1)} \end{bmatrix}$$
2022.09.27 - [Programming/DIP] - [NumPy] Broadcasting
Combined Indexing
fancy indexing은 나머지 indexing기법과도 조합하여 사용가능함.
x[2, [2, 0, 1]] # combination between simple indexing and fancy indexing
결과는 다음과 같음.
array([8, 6, 7])
x[::-1, [0,2]] # combination b/w slicing and fancy indexing
결과는 다음과 같음.
array([[6, 8],
[3, 5],
[0, 2]])
boolean mask와도 조합이 가능함.
mask = np.array([True, False, True])
cidx = np.array([2,0,1])
x[mask,cidx[:,np.newaxis]]
위의 코드는 다음과 같은 코드임.
x[[0,2],cidx[:,np.newaxis]]
- 주의할 건, boolean mask의 경우, broadcasting을 할 때
True
인 부분들만이 실제로 shape에 카운팅이 됨. - 위의 코드에서 boolean mask가 3개의 요소로 보이나 broadcasting 규칙을 적용할 때는 실제로는 2개의 요소만을 가진 ndarray로 간주됨.
- 때문에 broadcasting에서 각 축의 number of elements(요소의 수)가 맞지 않아 문제가 발생 할 수 있음. 주의필요.
Fancy indexing을 이용하여 특정 item의 값을 변경할 수 있으나, 같은 index가 여러번 나온다고 해도 변경연산이 누적(혹은 반복)되진 않음.
x = np.arange(10)
i = np.array([9, 1, 3, 9])
x[i] = x[i] +10
x
결과는 다음과 같음.
array([ 0, 11, 2, 13, 4, 5, 6, 7, 8, 19])
- 주의할 부분은 9를 index로 가지는 부분으로
- fancy indexing에서 2번 지정되었다고 10이 더해지는 연산이 2번 누적해서 일어나지 않음.
이같이 반복 처리를 하려면 at
메소드를 활용해야함.
x = np.arange(10)
np.add.at(x,i,10)
x
결과는 다음과 같음.
`array([ 0, 11, 2, 13, 4, 5, 6, 7, 8, 29])`
https://gist.github.com/dsaint31x/eb7a1fcc729ba3f349d7259002318976#file-fancyindexing-ipynb
'Programming > DIP' 카테고리의 다른 글
[DIP] Image Format (summary) (0) | 2022.12.05 |
---|---|
[DIP] Deconvolution: Richardson-Lucy deconvolution algorithm (0) | 2022.10.11 |
[DIP] OpenCV : Region of Interest (ROI) : Callback으로 구현. (0) | 2022.10.03 |
[DIP] opencv : Region of Interest (ROI) : cv2.selectROI (0) | 2022.10.03 |
[NumPy] Broadcasting (0) | 2022.09.27 |