파이썬3 노트

numpy 공부: [indexing] (1)

Jonchann 2018. 8. 7. 18:44

방학이 끝나기 전 까지는 딥 러닝 모델을 구현하고 싶어 선배에게 상담하니 일단 넘파이-파이토치 순으로 공부해야 된다고.

그래서 넘파이 퀵 튜토리얼부터 보는데 정말 인덱싱 부분은 이해가 빨리 빨리 안되어서 적으면서 좀 외워야겠다.


일단 순서는 SciPy.org - NumPy v1.15 - Indexing 에 나와있는 순서대로.



1. Single element indexing


x = np.arange(10) #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(x[2]) #2
print(x[-2]) #8

x[2]는 인덱스 2에 들어있는 값을 나타내고 x[-2]는 뒤에서 2번째 값을 나타낸다.


x.shape = (2, 5) #x.reshape((2, 5))
# x = [[0, 1, 2, 3, 4]
#      [5, 6, 7, 8, 9]]
print(x[1, 3]) #8
print(x[1, -1]) #9

x[1, 3]을 예로 들면, 1은 인덱스 1에 들어있는 행을 말하고 3은 1번째 행에서 인덱스 3에 들어있는 값을 말한다.

그러므로 [5, 6, 7, 8, 9]에서 인덱스 3인 8을 가져온다.

참고로 x[0]을 가져오라 한다면 인덱스 0에 들어있는 행을 출력한다: [0, 1, 2, 3, 4]

x[0][2]라는 표현도 가능한데 이는 x[0, 2]와 같은 값을 내놓으면서 더 비효율적이라 한다.



2. Other indexing option


x = np.aragne(10) #x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(x[2:5]) #[2, 3, 4]
print(x[:-7]) #[0, 1, 2]
print(x[1:7:2]) #[1, 3, 5]

x[ i : j ]라는 것은 x의 인덱스 i에 들어있는 값 부터 인덱스 j-1까지의 값을 나타낸다.

x[ i : j : k ]라는 것은 i부터 j-1까지의 범위 내에서 k개씩 뛰면서 가져오라는 것이다.


y = np.arange(35).reshape(5, 7)
# y = [[ 0,  1,  2,  3,  4,  5,  6],
#      [ 7,  8,  9, 10, 11, 12, 13],
#      [14, 15, 16, 17, 18, 19, 20],
#      [21, 22, 23, 24, 25, 26, 27],
#      [28, 29, 30, 31, 32, 33, 34]]
print(y[1:5:2, ::3])
# [[7, 10, 13],
#  [21, 24, 27]]

2 차원 행렬이기 때문에 위에서 적은 것과는 ::가 다른 역할을 한다.

y[1:5:2, ::3]에서 1:5:2는 행의 범위를 나타내고 있다. 인덱스 1에 해당하는 행부터 인덱스 5-1에 해당하는 행까지를 범위로 설정하고 있는 것이다. 마지막이 2 이므로 그 중에서 행을 하나씩 스킵하고 내놓으라는 것이다. 그러면 범위가 아래와 같이 좁혀진다.


[[7, 8, 9, 10, 11, 12, 13],

 [21, 22, 23,24,25, 26, 27]]


그 뒤의 ::3은 지금 구한 행의 범위에서 다시 열의 범위를 좁히는 역할을 한다.

::는 전체를 뜻하기 때문에 인덱스 0에 해당하는 열부터 마지막 열까지를 다시 범위로 잡고 그 안에서 3개씩 뛰라는 소리다.

그러므로 최종 출력 값은 아래와 같다.


[[7, 10, 13],

 [21, 24, 27]]



3. Index arrays


x = np.agrange(10, 1, -1) #x = [10, 9, ... , 3, 2]
print(x[np.array([3, 3, 1, 8])]) #[7, 7, 9, 2]

인덱스 안에 1차원 배열이 들어 있는데 꽤 간단하다.

그냥 저 숫자에 해당하는 인덱스 위치에 들어있는 값을 출력하면 된다.


print(x[np.array([[1, 1], [2, 3]])] 
# [[9, 9],
#  [8, 7]]

이번엔 1차원 배열을 2차원으로 잘라내는 일을 하는데 차원만 바뀌었다 뿐이지 위와 동일하게 적혀있는 숫자에 해당하는 인덱스의 값을 찾아 2차원으로 찾아내면 된다.



4. Indexing multi-dimentional arrays


y = np.arange(35).reshape(5, 7)
# y = [[0, 1, 2, 3, 4, 5, 6],
#      [7, 8, 9, 10, 11, 12, 13],
#      [14, 15, 16, 17, 18, 19, 20],
#      [21, 22, 23, 24, 25, 26, 27],
#      [28, 29, 30, 31, 32, 33, 34]]
y[np.array([0,2,4]), np.array([0,1,2])] #[ 0, 15, 30]

4번째 코드와 비슷한 코드다.

먼저 np.array([0, 2, 4])부터 보면 2차원 텐서 y의 0번째, 2번째, 4번째 행을 가져오라는 소리이다.

그러면 범위가 아래와 같이 좁혀진다.


[[0, 1, 2, 3, 4, 5, 6],

 [14, 15, 16, 17, 18, 19, 20],

 [28, 29, 30, 31, 32, 33, 34]]


뒤에 있는 np.array([0, 1, 2])는 위에서 설정한 행의 범위 내에서 0번째, 1번째, 2번째 열에 있는 요소를 가져오라는 소리이므로 출력값은 [0, 15, 30]이 된다.


y[np.array([0,2,4]), np.array([0,1])]
: shape mismatch: objects cannot be
broadcast to a single shape

대신 배열의 숫자는 맞춰줘야지 안 그러면 에러가 난다.


y[np.array([0,2,4]), 1] #[ 1, 15, 29]

np.array([0, 2, 4])부분은 똑같으니 패스하고 뒤의 1만 보면, 열 인덱스 1에 있는 숫자는 다 가져 오라는 것이므로 출력값은 [1, 15, 29]가 된다.