Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

파이썬 NumPy 기본 슬라이싱과 고급 인덱싱 완벽 정리

NumPy의 ndarray는 파이썬 표준 문법인 x[obj] 형식을 사용해 인덱싱할 수 있습니다. 여기서 x는 배열이고 obj는 선택(selection)에 해당합니다.

NumPy에서 제공하는 인덱싱 방식은 크게 세 가지입니다.

  • 필드 접근(field access)
  • 기본 슬라이싱(basic slicing)
  • 고급 인덱싱(advanced indexing)

어떤 인덱싱이 적용될지는 obj가 무엇인지에 따라 결정됩니다. 이 글에서는 그중에서도 가장 많이 활용되는 기본 슬라이싱고급 인덱싱을 중점적으로 다룹니다.

또한 고급 인덱싱은 다음 두 가지로 나눌 수 있습니다.

  • 정수 배열 인덱싱(Integer array indexing)
  • 불리언 인덱싱(Boolean indexing)

기본 슬라이싱(Basic Slicing)

기본 슬라이싱은 파이썬의 슬라이싱 개념을 n차원으로 확장한 것입니다. 파이썬의 slice 객체처럼 start(시작), stop(종료), step(간격) 세 가지 매개변수를 지정하여 구성할 수 있으며, 이 slice 객체를 배열에 전달하면 배열의 일부를 추출할 수 있습니다.

예제 1

import numpy as np
arr = np.arange(25)
s = slice(2, 21, 4)
print(arr[s])

출력 결과

[ 2 6 10 14 18]

위 예제에서는 먼저 arange() 함수로 ndarray 객체(arr)를 생성했습니다. 그다음 start=2, stop=21, step=4 값을 지정해 slice 객체(s)를 만들었습니다. 이 slice 객체를 ndarray에 전달하면 인덱스 2부터 21까지 4씩 건너뛰며 추출한 배열 조각을 얻을 수 있습니다.

같은 코드를 더 간결하게 작성하는 방법도 있습니다.

# 위 프로그램을 다른 방식으로 작성
import numpy as np
arr = np.arange(25)
s = arr[2:21:4]
print(s)

출력 결과

[ 2 6 10 14 18]

단일 항목 슬라이싱

배열에서 특정 위치의 단일 요소 하나만 가져오려면 인덱스를 직접 지정하면 됩니다.

# 배열에서 단일 항목 슬라이싱
import numpy as np
arr = np.arange(10)
s = arr[9]
print(s)

출력 결과

9

특정 인덱스부터 끝까지 슬라이싱

시작 인덱스만 지정하고 종료 인덱스를 생략하면 해당 위치부터 배열 끝까지 모두 추출합니다.

# 특정 인덱스부터 시작하는 슬라이싱
import numpy as np
arr = np.arange(10)
s = arr[3:]
print(s)

출력 결과

[3 4 5 6 7 8 9]

인덱스 범위 사이 슬라이싱

시작 인덱스와 종료 인덱스를 함께 지정하면 그 사이의 요소들만 추출합니다. 단, 종료 인덱스의 요소는 포함되지 않습니다.

# 인덱스 사이의 항목 슬라이싱
import numpy as np
arr = np.arange(10)
s = arr[3:7]
print(s)

출력 결과

[3 4 5 6]

위에서 살펴본 두 가지 방법은 다차원 ndarray에도 동일하게 적용할 수 있습니다.

# 다차원 배열 슬라이싱
import numpy as np
arr = np.array([[[1],[2],[3]], [[4],[5],[6]], [[7],[8],[9]]])
s = arr[1:]
print(s)

출력 결과

[[[4]
[5]
[6]]
[[7]
[8]
[9]]]

고급 인덱싱(Advanced Indexing)

정수 배열 인덱싱(Integer Array Indexing)

먼저 간단한 정수 배열을 생성해 보겠습니다.

arr = np.array([[1,2],[3,4],[5,6]])
print(arr)

출력 결과

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

다차원 ndarray에서 행 인덱스 [0, 1, 2]와 열 인덱스 [1, 0, 1]에 해당하는 특정 요소들을 선택해 보겠습니다.

import numpy as np
arr = np.array([[1,2],[3,4],[5,6]])
s = arr[[0, 1, 2], [1, 0, 1]]
print(s)

출력 결과

[2 3 6]

인덱스 0으로 선택하면 첫 번째 행 전체가 반환됩니다.

>>> arr = np.array([[1,2],[3,4],[5,6]])
>>> print(arr[0])
[1 2]

마찬가지로 배열에서 단일 요소를 선택할 수도 있습니다. 예를 들어 행 인덱스 1, 열 인덱스 1에 해당하는 요소를 선택하면 값 4가 반환됩니다.

>>> print(arr[[1], [1]])
[4]

선택한 요소에 덧셈 같은 산술 연산을 수행한 결과를 반환할 수도 있습니다.

>>> print(arr[[1], [1]] + 1)
[5]

인덱스로 가져온 값은 1 증가했지만, 원본 배열은 그대로 유지됩니다.

>>> arr
array([[1, 2],
[3, 4],
[5, 6]])

반면 += 연산자를 사용하면 실제 배열의 값이 변경되어 새로운 복사본이 반환됩니다.

>>> arr[[1], [1]] += 1
>>> arr
array([[1, 2],
[3, 5],
[5, 6]])

불리언 인덱싱(Boolean Indexing)

불리언 인덱싱은 조건 연산의 결과를 기준으로 요소를 필터링할 때 사용합니다. 먼저 4x3 배열을 생성해 보겠습니다.

>>> arr = np.array([[0,1,2], [3,4,5], [6,7,8], [9,10,11]])
>>> arr
array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])

값이 1인 요소만 반환합니다.

>>> arr[arr == 1]
array([1])

짝수인 요소만 반환합니다.

>>> arr[arr % 2 == 0]
array([ 0, 2, 4, 6, 8, 10])

이처럼 불리언 인덱싱을 활용하면 복잡한 반복문 없이도 조건에 맞는 데이터를 손쉽게 추출할 수 있어, 데이터 분석과 전처리 작업에서 매우 유용하게 활용됩니다.