기록하는 습관

[Numpy] 004. 배열 인덱싱 & 슬라이싱 (Indexing & Slicing) 본문

Python/Numpy

[Numpy] 004. 배열 인덱싱 & 슬라이싱 (Indexing & Slicing)

Avalla 2023. 8. 6. 14:09

Indexing, Slicing

import numpy as np

1차원 배열의 인덱싱&슬라이싱은 리스트와 유사하다.

array = np.array(range(10))
print( "array :", array )
print( "array[2] :", array[2] )
print( "array[-2] :", array[-2] )
print( "array[2:3] :", array[2:3] )
array : [0 1 2 3 4 5 6 7 8 9]
array[2] : 2
array[-2] : 8
array[2:3] : [2]
array = np.array(range(10))
print( "array :", array )
print( "array[2::3] :", array[2::3] )
print( "array[::5] :", array[::5] )
print( "array[5::] :", array[5::] )
array : [0 1 2 3 4 5 6 7 8 9]
array[2::3] : [2 5 8]
array[::5] : [0 5]
array[5::] : [5 6 7 8 9]
array = np.array(range(10))
print( "array :", array )
print( "array[5::-1] :", array[5::-1] )
print( "array[-1::5] :", array[-1::5] )
print( "array[-1::-3] :", array[-1::-3] )
array : [0 1 2 3 4 5 6 7 8 9]
array[5::-1] : [5 4 3 2 1 0]
array[-1::5] : [9]
array[-1::-3] : [9 6 3 0]

아래와 같이 2차원 이상의 배열은 리스트와 달리 [:, :] 와 같은 인덱싱&슬라이싱이 가능하다.

array = np.array(range(20)).reshape(4,5)
print( "array :\n", array )
print( "array.shape :\n", array.shape )
print( "array[2][3] :\n", array[2][3] )
print( "array[2,3] :\n", array[2,3] ) # 리스트와 다른 점
array :
 [[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]]
array.shape :
 (4, 5)
array[2][3] :
 13
array[2,3] :
 13
array = np.array(range(20)).reshape(4,5)
print( "array :\n", array )
print( "array[:, 2::2] :\n", array[:, 2::2] )
print( "array[2::2, 3] :\n", array[2::2, 3] )
print( "array[::2] :\n", array[::2] )
print( "array[2::, 1::3] :\n", array[2::, 1::3] )
array :
 [[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]]
array[:, 2::2] :
 [[ 2  4]
 [ 7  9]
 [12 14]
 [17 19]]
array[2::2, 3] :
 [13]
array[::2] :
 [[ 0  1  2  3  4]
 [10 11 12 13 14]]
array[2::, 1::3] :
 [[11 14]
 [16 19]]
array = np.array(range(20)).reshape(2,2,5)
print( "array :\n", array )
print( "array[1:2, :, 3:] :\n", array[1:2, :, 3:] )
print( "array[:, 1, 2::2] :\n", array[:, 1, 2::2] )
print( "array[:, :1] :\n", array[:, :1] )
print( "array[1, :, 1::3] :\n", array[1, :, 1::3] )
array :
 [[[ 0  1  2  3  4]
  [ 5  6  7  8  9]]

 [[10 11 12 13 14]
  [15 16 17 18 19]]]
array[1:2, :, 3:] :
 [[[13 14]
  [18 19]]]
array[:, 1, 2::2] :
 [[ 7  9]
 [17 19]]
array[:, :1] :
 [[[ 0  1  2  3  4]]

 [[10 11 12 13 14]]]
array[1, :, 1::3] :
 [[11 14]
 [16 19]]

Fancy Indexing

배열[인덱스배열] or 배열.take(인덱스배열)

기본 list와 달리 Numpy ndarray 배열에 지원되는 유용한 인덱싱 기법으로, 아래 예시로 확인할 수 있다.

a = np.array(['도', '레', '미', '파', '솔', '라', '시', '♪'], str)
b = np.array([4, 4, 5, 5, 4, 4, 2, 7, 4, 4, 2, 2, 1, 7])
print( a[b] )
print( a.take(b) )
['솔' '솔' '라' '라' '솔' '솔' '미' '♪' '솔' '솔' '미' '미' '레' '♪']
['솔' '솔' '라' '라' '솔' '솔' '미' '♪' '솔' '솔' '미' '미' '레' '♪']
다차원 행렬에 대해서도 가능하다.

아래 예시에서 a는 2차원 행렬이므로, a[배열1, 배열2] 에 대해 배열1은 0차원의 인덱스, 배열2는 1차원의 인덱스를 가리킨다. 따라서 배열1과 배열2는 같은 shape이어야 하고, a[배열1, 배열2]의 shape은 배열1, 배열2의 shape과 같다.
a = np.arange(6).reshape(3,2)
b = [1,0,2]
c = [1,0,1]
print( a )
print( "▶ a[b] : a[[1,0,2]]\n", a[b] ) # 행 순서만 바뀜
print( "▶ a[b,c] : a[[1,0,2], [1,0,1]]\n", a[b,c] )
[[0 1]
 [2 3]
 [4 5]]
▶ a[b] : a[[1,0,2]]
 [[2 3]
 [0 1]
 [4 5]]
▶ a[b,c] : a[[1,0,2], [1,0,1]]
 [3 0 5]
a = np.array([["A", "B"], ["-", "#"], [1,2]])
d = [[2,1], [1,0]]
e = [[1,1], [1,0]]
print( a )
print( "▶ a[d,e] : a[[[2,1], [1,0]], [[1,1], [1,0]]]") # 헷갈리지 않게 조심
print( a[d,e] )
print( "▶ [[a[2,1], a[1,1]], [a[1,1], a[0,0]]]\n", 
      np.array([[a[2,1], a[1,1]], [a[1,1], a[0,0]]]) ) # 같은 결과
[['A' 'B']
 ['-' '#']
 ['1' '2']]
▶ a[d,e] : a[[[2,1], [1,0]], [[1,1], [1,0]]]
[['2' '#']
 ['#' 'A']]
▶ [[a[2,1], a[1,1]], [a[1,1], a[0,0]]]
 [['2' '#']
 ['#' 'A']]